From 35a1e5d180ba3e6cb4996d47edc69cccdd28dc42 Mon Sep 17 00:00:00 2001 From: sorgelig Date: Sun, 22 Oct 2017 09:22:56 +0800 Subject: [PATCH] Initial port. --- .gitignore | 37 + MacPlus-lite.qsf | 376 ++++ MacPlus-lite.srf | 16 + MacPlus.qpf | 32 + MacPlus.qsf | 374 ++++ MacPlus.srf | 51 + MacPlus.sv | 574 +++++ TG68K_ALU.vhd | 932 ++++++++ TG68K_Pack.vhd | 250 +++ TG68KdotC_Kernel.vhd | 3318 ++++++++++++++++++++++++++++ addrController_top.v | 151 ++ addrDecoder.v | 132 ++ clean.bat | 37 + dataController_top.v | 299 +++ floppy.v | 340 +++ floppy_track_encoder.v | 367 ++++ iwm.v | 308 +++ jtag.cdf | 15 + jtag_lite.cdf | 15 + ncr5380.v | 297 +++ ps2_kbd.sv | 654 ++++++ ps2_mouse.v | 94 + readme.md | 51 + release/Disk605.dsk | Bin 0 -> 819200 bytes release/boot.rom | Bin 0 -> 131072 bytes release/empty_hdd.zip | Bin 0 -> 26152 bytes scc.v | 587 +++++ scsi.v | 340 +++ sys/build_id.tcl | 35 + sys/ddram.sv | 153 ++ sys/hdmi_config.sv | 265 +++ sys/hps_io.v | 642 ++++++ sys/hq2x.sv | 416 ++++ sys/i2c.v | 69 + sys/i2s.v | 85 + sys/ip/avalon_combiner.v | 60 + sys/ip/avalon_combiner_hw.tcl | 204 ++ sys/ip/de10_hps_hw.tcl | 3706 ++++++++++++++++++++++++++++++++ sys/ip/reset_source.v | 48 + sys/ip/reset_source_hw.tcl | 151 ++ sys/lpf48k.sv | 100 + sys/osd.v | 168 ++ sys/pattern_vg.v | 120 ++ sys/pll.qip | 337 +++ sys/pll.v | 255 +++ sys/pll/pll_0002.qip | 4 + sys/pll/pll_0002.v | 90 + sys/pll_hdmi.qip | 337 +++ sys/pll_hdmi.v | 252 +++ sys/pll_hdmi/pll_hdmi_0002.qip | 4 + sys/pll_hdmi/pll_hdmi_0002.v | 87 + sys/scandoubler.v | 186 ++ sys/sdram.sv | 194 ++ sys/sigma_delta_dac.v | 33 + sys/spdif.v | 392 ++++ sys/sync_vg.v | 123 ++ sys/sys.qip | 20 + sys/sys_top.sdc | 27 + sys/sys_top.v | 681 ++++++ sys/sysmem.qip | 2 + sys/sysmem.sv | 519 +++++ sys/vga_out.sv | 65 + sys/video_mixer.sv | 167 ++ sys/vip.qip | 2 + sys/vip.qsys | 1097 ++++++++++ sys/vip_config.sv | 169 ++ via.v | 365 ++++ video.v | 163 ++ 68 files changed, 21440 insertions(+) create mode 100644 .gitignore create mode 100644 MacPlus-lite.qsf create mode 100644 MacPlus-lite.srf create mode 100644 MacPlus.qpf create mode 100644 MacPlus.qsf create mode 100644 MacPlus.srf create mode 100644 MacPlus.sv create mode 100644 TG68K_ALU.vhd create mode 100644 TG68K_Pack.vhd create mode 100644 TG68KdotC_Kernel.vhd create mode 100644 addrController_top.v create mode 100644 addrDecoder.v create mode 100644 clean.bat create mode 100644 dataController_top.v create mode 100644 floppy.v create mode 100644 floppy_track_encoder.v create mode 100644 iwm.v create mode 100644 jtag.cdf create mode 100644 jtag_lite.cdf create mode 100644 ncr5380.v create mode 100644 ps2_kbd.sv create mode 100644 ps2_mouse.v create mode 100644 readme.md create mode 100644 release/Disk605.dsk create mode 100644 release/boot.rom create mode 100644 release/empty_hdd.zip create mode 100644 scc.v create mode 100644 scsi.v create mode 100644 sys/build_id.tcl create mode 100644 sys/ddram.sv create mode 100644 sys/hdmi_config.sv create mode 100644 sys/hps_io.v create mode 100644 sys/hq2x.sv create mode 100644 sys/i2c.v create mode 100644 sys/i2s.v create mode 100644 sys/ip/avalon_combiner.v create mode 100644 sys/ip/avalon_combiner_hw.tcl create mode 100644 sys/ip/de10_hps_hw.tcl create mode 100644 sys/ip/reset_source.v create mode 100644 sys/ip/reset_source_hw.tcl create mode 100644 sys/lpf48k.sv create mode 100644 sys/osd.v create mode 100644 sys/pattern_vg.v create mode 100644 sys/pll.qip create mode 100644 sys/pll.v create mode 100644 sys/pll/pll_0002.qip create mode 100644 sys/pll/pll_0002.v create mode 100644 sys/pll_hdmi.qip create mode 100644 sys/pll_hdmi.v create mode 100644 sys/pll_hdmi/pll_hdmi_0002.qip create mode 100644 sys/pll_hdmi/pll_hdmi_0002.v create mode 100644 sys/scandoubler.v create mode 100644 sys/sdram.sv create mode 100644 sys/sigma_delta_dac.v create mode 100644 sys/spdif.v create mode 100644 sys/sync_vg.v create mode 100644 sys/sys.qip create mode 100644 sys/sys_top.sdc create mode 100644 sys/sys_top.v create mode 100644 sys/sysmem.qip create mode 100644 sys/sysmem.sv create mode 100644 sys/vga_out.sv create mode 100644 sys/video_mixer.sv create mode 100644 sys/vip.qip create mode 100644 sys/vip.qsys create mode 100644 sys/vip_config.sv create mode 100644 via.v create mode 100644 video.v diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..93fd271 --- /dev/null +++ b/.gitignore @@ -0,0 +1,37 @@ +db +greybox_tmp +incremental_db +output_files +simulation +hc_output +scaler +hps_isw_handoff +vip +*_sim +.qsys_edit +PLLJ_PLLSPE_INFO.txt +*.bak +*.orig +*.rej +*.qdf +*.rpt +*.smsg +*.summary +*.done +*.jdi +*.pin +*.sof +*.qws +*.ppf +*.ddb +build_id.v +c5_pin_model_dump.txt +*.sopcinfo +*.csv +*.f +*.cmp +*.sip +*.spd +*.bsf +*~ +*.xml diff --git a/MacPlus-lite.qsf b/MacPlus-lite.qsf new file mode 100644 index 0000000..062f3fc --- /dev/null +++ b/MacPlus-lite.qsf @@ -0,0 +1,376 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 2017 Intel Corporation. All rights reserved. +# Your use of Intel Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Intel Program License +# Subscription Agreement, the Intel Quartus Prime License Agreement, +# the Intel MegaCore Function License Agreement, or other +# applicable license agreement, including, without limitation, +# that your use is for the sole purpose of programming logic +# devices manufactured by Intel and sold by Intel or its +# authorized distributors. Please refer to the applicable +# agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus Prime +# Version 16.1.2 Build 203 01/18/2017 SJ Standard Edition +# Date created = 01:53:32 April 20, 2017 +# +# -------------------------------------------------------------------------- # + +set_global_assignment -name VERILOG_MACRO "LITE=1" + +set_global_assignment -name FAMILY "Cyclone V" +set_global_assignment -name DEVICE 5CSEBA6U23I7 +set_global_assignment -name TOP_LEVEL_ENTITY sys_top +set_global_assignment -name ORIGINAL_QUARTUS_VERSION 16.1.2 +set_global_assignment -name LAST_QUARTUS_VERSION "17.0.1 Standard Edition" +set_global_assignment -name PROJECT_CREATION_TIME_DATE "01:53:30 APRIL 20, 2017" +set_global_assignment -name DEVICE_FILTER_PACKAGE UFBGA +set_global_assignment -name DEVICE_FILTER_PIN_COUNT 672 +set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 7 + +set_global_assignment -name GENERATE_RBF_FILE ON +set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files +set_global_assignment -name NUM_PARALLEL_PROCESSORS ALL +set_global_assignment -name SAVE_DISK_SPACE OFF +set_global_assignment -name SMART_RECOMPILE ON +set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top +set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top +set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top +set_global_assignment -name MIN_CORE_JUNCTION_TEMP "-40" +set_global_assignment -name MAX_CORE_JUNCTION_TEMP 100 +set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW" +set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)" +set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS OFF +set_global_assignment -name OPTIMIZE_POWER_DURING_FITTING OFF +set_global_assignment -name FINAL_PLACEMENT_OPTIMIZATION ALWAYS +set_global_assignment -name FITTER_EFFORT "STANDARD FIT" +set_global_assignment -name OPTIMIZATION_MODE BALANCED +set_global_assignment -name SEED 1 + +#============================================================ +# ADC +#============================================================ +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ADC_CONVST +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ADC_SCK +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ADC_SDI +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ADC_SDO +set_location_assignment PIN_U9 -to ADC_CONVST +set_location_assignment PIN_V10 -to ADC_SCK +set_location_assignment PIN_AC4 -to ADC_SDI +set_location_assignment PIN_AD4 -to ADC_SDO + +#============================================================ +# ARDUINO +#============================================================ +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[6] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[7] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[8] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[9] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[10] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[11] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[12] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[13] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[14] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[15] +set_location_assignment PIN_AG9 -to ARDUINO_IO[3] +set_location_assignment PIN_U14 -to ARDUINO_IO[4] +set_location_assignment PIN_U13 -to ARDUINO_IO[5] +set_location_assignment PIN_AG8 -to ARDUINO_IO[6] +set_location_assignment PIN_AH8 -to ARDUINO_IO[7] +set_location_assignment PIN_AF17 -to ARDUINO_IO[8] +set_location_assignment PIN_AE15 -to ARDUINO_IO[9] +set_location_assignment PIN_AF15 -to ARDUINO_IO[10] +set_location_assignment PIN_AG16 -to ARDUINO_IO[11] +set_location_assignment PIN_AH11 -to ARDUINO_IO[12] +set_location_assignment PIN_AH12 -to ARDUINO_IO[13] +set_location_assignment PIN_AH9 -to ARDUINO_IO[14] +set_location_assignment PIN_AG11 -to ARDUINO_IO[15] + +#============================================================ +# SDIO +#============================================================ +set_location_assignment PIN_AF25 -to SDIO_DAT[0] +set_location_assignment PIN_AF23 -to SDIO_DAT[1] +set_location_assignment PIN_AD26 -to SDIO_DAT[2] +set_location_assignment PIN_AF28 -to SDIO_DAT[3] +set_location_assignment PIN_AF27 -to SDIO_CMD +set_location_assignment PIN_AH26 -to SDIO_CLK +set_location_assignment PIN_AH7 -to SDIO_CD + +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDIO_* + +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDIO_* +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to SDIO_DAT[*] +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to SDIO_CMD +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to SDIO_CD + +#============================================================ +# VGA +#============================================================ +set_location_assignment PIN_AE17 -to VGA_R[0] +set_location_assignment PIN_AE20 -to VGA_R[1] +set_location_assignment PIN_AF20 -to VGA_R[2] +set_location_assignment PIN_AH18 -to VGA_R[3] +set_location_assignment PIN_AH19 -to VGA_R[4] +set_location_assignment PIN_AF21 -to VGA_R[5] + +set_location_assignment PIN_AE19 -to VGA_G[0] +set_location_assignment PIN_AG15 -to VGA_G[1] +set_location_assignment PIN_AF18 -to VGA_G[2] +set_location_assignment PIN_AG18 -to VGA_G[3] +set_location_assignment PIN_AG19 -to VGA_G[4] +set_location_assignment PIN_AG20 -to VGA_G[5] + +set_location_assignment PIN_AG21 -to VGA_B[0] +set_location_assignment PIN_AA20 -to VGA_B[1] +set_location_assignment PIN_AE22 -to VGA_B[2] +set_location_assignment PIN_AF22 -to VGA_B[3] +set_location_assignment PIN_AH23 -to VGA_B[4] +set_location_assignment PIN_AH21 -to VGA_B[5] + +set_location_assignment PIN_AH22 -to VGA_HS +set_location_assignment PIN_AG24 -to VGA_VS + +set_location_assignment PIN_AH27 -to VGA_EN +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to VGA_EN + +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_* +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to VGA_* + +#============================================================ +# AUDIO +#============================================================ +set_location_assignment PIN_AC24 -to AUDIO_L +set_location_assignment PIN_AE25 -to AUDIO_R +set_location_assignment PIN_AG26 -to AUDIO_SPDIF +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to AUDIO_* +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to AUDIO_* + +#============================================================ +# SDRAM +#============================================================ +set_location_assignment PIN_Y11 -to SDRAM_A[0] +set_location_assignment PIN_AA26 -to SDRAM_A[1] +set_location_assignment PIN_AA13 -to SDRAM_A[2] +set_location_assignment PIN_AA11 -to SDRAM_A[3] +set_location_assignment PIN_W11 -to SDRAM_A[4] +set_location_assignment PIN_Y19 -to SDRAM_A[5] +set_location_assignment PIN_AB23 -to SDRAM_A[6] +set_location_assignment PIN_AC23 -to SDRAM_A[7] +set_location_assignment PIN_AC22 -to SDRAM_A[8] +set_location_assignment PIN_C12 -to SDRAM_A[9] +set_location_assignment PIN_AB26 -to SDRAM_A[10] +set_location_assignment PIN_AD17 -to SDRAM_A[11] +set_location_assignment PIN_D12 -to SDRAM_A[12] +set_location_assignment PIN_Y17 -to SDRAM_BA[0] +set_location_assignment PIN_AB25 -to SDRAM_BA[1] + +set_location_assignment PIN_E8 -to SDRAM_DQ[0] +set_location_assignment PIN_V12 -to SDRAM_DQ[1] +set_location_assignment PIN_D11 -to SDRAM_DQ[2] +set_location_assignment PIN_W12 -to SDRAM_DQ[3] +set_location_assignment PIN_AH13 -to SDRAM_DQ[4] +set_location_assignment PIN_D8 -to SDRAM_DQ[5] +set_location_assignment PIN_AH14 -to SDRAM_DQ[6] +set_location_assignment PIN_AF7 -to SDRAM_DQ[7] +set_location_assignment PIN_AE24 -to SDRAM_DQ[8] +set_location_assignment PIN_AD23 -to SDRAM_DQ[9] +set_location_assignment PIN_AE6 -to SDRAM_DQ[10] +set_location_assignment PIN_AE23 -to SDRAM_DQ[11] +set_location_assignment PIN_AG14 -to SDRAM_DQ[12] +set_location_assignment PIN_AD5 -to SDRAM_DQ[13] +set_location_assignment PIN_AF4 -to SDRAM_DQ[14] +set_location_assignment PIN_AH3 -to SDRAM_DQ[15] +set_location_assignment PIN_AG13 -to SDRAM_DQML +set_location_assignment PIN_AF13 -to SDRAM_DQMH + +set_location_assignment PIN_AD20 -to SDRAM_CLK +set_location_assignment PIN_AG10 -to SDRAM_CKE + +set_location_assignment PIN_AA19 -to SDRAM_nWE +set_location_assignment PIN_AA18 -to SDRAM_nCAS +set_location_assignment PIN_Y18 -to SDRAM_nCS +set_location_assignment PIN_W14 -to SDRAM_nRAS + +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_* +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_* +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_A* +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_BA* +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQ[*] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQM* +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_n* +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ[*] +set_instance_assignment -name ALLOW_SYNCH_CTRL_USAGE OFF -to *|SDRAM_* + +#============================================================ +# I/O +#============================================================ +set_location_assignment PIN_Y15 -to LED_USER +set_location_assignment PIN_AA15 -to LED_HDD +set_location_assignment PIN_AG28 -to LED_POWER + +set_location_assignment PIN_AH24 -to BTN_USER +set_location_assignment PIN_AG25 -to BTN_OSD +set_location_assignment PIN_AG23 -to BTN_RESET + +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED_* +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to BTN_* +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to BTN_* + +#============================================================ +# CLOCK +#============================================================ +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FPGA_CLK1_50 +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FPGA_CLK2_50 +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FPGA_CLK3_50 +set_location_assignment PIN_V11 -to FPGA_CLK1_50 +set_location_assignment PIN_Y13 -to FPGA_CLK2_50 +set_location_assignment PIN_E11 -to FPGA_CLK3_50 + +#============================================================ +# HDMI +#============================================================ +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_I2C_SCL +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_I2C_SDA +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_I2S +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_LRCLK +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_MCLK +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_SCLK +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_CLK +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_DE +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[6] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[7] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[8] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[9] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[10] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[11] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[12] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[13] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[14] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[15] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[16] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[17] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[18] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[19] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[20] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[21] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[22] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[23] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_HS +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_INT +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_VS +set_location_assignment PIN_U10 -to HDMI_I2C_SCL +set_location_assignment PIN_AA4 -to HDMI_I2C_SDA +set_location_assignment PIN_T13 -to HDMI_I2S +set_location_assignment PIN_T11 -to HDMI_LRCLK +set_location_assignment PIN_U11 -to HDMI_MCLK +set_location_assignment PIN_T12 -to HDMI_SCLK +set_location_assignment PIN_AG5 -to HDMI_TX_CLK +set_location_assignment PIN_AD19 -to HDMI_TX_DE +set_location_assignment PIN_AD12 -to HDMI_TX_D[0] +set_location_assignment PIN_AE12 -to HDMI_TX_D[1] +set_location_assignment PIN_W8 -to HDMI_TX_D[2] +set_location_assignment PIN_Y8 -to HDMI_TX_D[3] +set_location_assignment PIN_AD11 -to HDMI_TX_D[4] +set_location_assignment PIN_AD10 -to HDMI_TX_D[5] +set_location_assignment PIN_AE11 -to HDMI_TX_D[6] +set_location_assignment PIN_Y5 -to HDMI_TX_D[7] +set_location_assignment PIN_AF10 -to HDMI_TX_D[8] +set_location_assignment PIN_Y4 -to HDMI_TX_D[9] +set_location_assignment PIN_AE9 -to HDMI_TX_D[10] +set_location_assignment PIN_AB4 -to HDMI_TX_D[11] +set_location_assignment PIN_AE7 -to HDMI_TX_D[12] +set_location_assignment PIN_AF6 -to HDMI_TX_D[13] +set_location_assignment PIN_AF8 -to HDMI_TX_D[14] +set_location_assignment PIN_AF5 -to HDMI_TX_D[15] +set_location_assignment PIN_AE4 -to HDMI_TX_D[16] +set_location_assignment PIN_AH2 -to HDMI_TX_D[17] +set_location_assignment PIN_AH4 -to HDMI_TX_D[18] +set_location_assignment PIN_AH5 -to HDMI_TX_D[19] +set_location_assignment PIN_AH6 -to HDMI_TX_D[20] +set_location_assignment PIN_AG6 -to HDMI_TX_D[21] +set_location_assignment PIN_AF9 -to HDMI_TX_D[22] +set_location_assignment PIN_AE8 -to HDMI_TX_D[23] +set_location_assignment PIN_T8 -to HDMI_TX_HS +set_location_assignment PIN_AF11 -to HDMI_TX_INT +set_location_assignment PIN_V13 -to HDMI_TX_VS + +#============================================================ +# KEY +#============================================================ +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to KEY[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to KEY[1] +set_location_assignment PIN_AH17 -to KEY[0] +set_location_assignment PIN_AH16 -to KEY[1] + +#============================================================ +# LED +#============================================================ +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[6] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[7] +set_location_assignment PIN_W15 -to LED[0] +set_location_assignment PIN_AA24 -to LED[1] +set_location_assignment PIN_V16 -to LED[2] +set_location_assignment PIN_V15 -to LED[3] +set_location_assignment PIN_AF26 -to LED[4] +set_location_assignment PIN_AE26 -to LED[5] +set_location_assignment PIN_Y16 -to LED[6] +set_location_assignment PIN_AA23 -to LED[7] + +#============================================================ +# SW +#============================================================ +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[3] +set_location_assignment PIN_Y24 -to SW[0] +set_location_assignment PIN_W24 -to SW[1] +set_location_assignment PIN_W21 -to SW[2] +set_location_assignment PIN_W20 -to SW[3] + +set_global_assignment -name PRE_FLOW_SCRIPT_FILE "quartus_sh:sys/build_id.tcl" + +set_global_assignment -name CDF_FILE jtag_lite.cdf +set_global_assignment -name QIP_FILE sys/sys.qip +set_global_assignment -name QIP_FILE sys/sysmem.qip +set_global_assignment -name VERILOG_FILE scsi.v +set_global_assignment -name VERILOG_FILE ncr5380.v +set_global_assignment -name VERILOG_FILE floppy_track_encoder.v +set_global_assignment -name VERILOG_FILE floppy.v +set_global_assignment -name SYSTEMVERILOG_FILE ps2_kbd.sv +set_global_assignment -name VERILOG_FILE ps2_mouse.v +set_global_assignment -name VHDL_FILE TG68K_Pack.vhd +set_global_assignment -name VHDL_FILE TG68K_ALU.vhd +set_global_assignment -name VHDL_FILE TG68KdotC_Kernel.vhd +set_global_assignment -name VERILOG_FILE scc.v +set_global_assignment -name VERILOG_FILE iwm.v +set_global_assignment -name VERILOG_FILE via.v +set_global_assignment -name VERILOG_FILE addrDecoder.v +set_global_assignment -name VERILOG_FILE addrController_top.v +set_global_assignment -name VERILOG_FILE dataController_top.v +set_global_assignment -name VERILOG_FILE video.v +set_global_assignment -name SYSTEMVERILOG_FILE MacPlus.sv +set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/MacPlus-lite.srf b/MacPlus-lite.srf new file mode 100644 index 0000000..8aa3b1b --- /dev/null +++ b/MacPlus-lite.srf @@ -0,0 +1,16 @@ +{ "" "" "" "Inferred RAM node \"emu:emu\|mister_io:mister_io\|ps2_kbd_fifo_rtl_0\" from synchronous design logic. Pass-through logic has been added to match the read-during-write behavior of the original design." { } { } 0 276020 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Inferred RAM node \"emu:emu\|mister_io:mister_io\|ps2_mouse_fifo_rtl_0\" from synchronous design logic. Pass-through logic has been added to match the read-during-write behavior of the original design." { } { } 0 276020 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Synthesized away node \"emu:emu\|pll:pll\|pll_0002:pll_inst\|altera_pll:altera_pll_i\|outclk_wire\[2\]\"" { } { } 0 14320 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "RST port on the PLL is not properly connected on instance emu:emu\|pll:pll\|pll_0002:pll_inst\|altera_pll:altera_pll_i\|general\[1\].gpll. The reset port on the PLL should be connected. If the PLL loses lock for any reason, you might need to manually reset the PLL in order to re-establish lock to the reference clock." { } { } 0 0 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "RST port on the PLL is not properly connected on instance emu:emu\|pll:pll\|pll_0002:pll_inst\|altera_pll:altera_pll_i\|general\[0\].gpll. The reset port on the PLL should be connected. If the PLL loses lock for any reason, you might need to manually reset the PLL in order to re-establish lock to the reference clock." { } { } 0 0 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Ignored locations or region assignments to the following nodes" { } { } 0 15705 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "RST port on the PLL is not properly connected on instance emu:emu\|pll:pll\|pll_0002:pll_inst\|altera_pll:altera_pll_i\|general\[2\].gpll. The reset port on the PLL should be connected. If the PLL loses lock for any reason, you might need to manually reset the PLL in order to re-establish lock to the reference clock." { } { } 0 0 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Verilog HDL or VHDL warning at de10_top.v(129): object \"io_win\" assigned a value but never read" { } { } 0 10036 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Verilog HDL or VHDL warning at de10_top.v(134): object \"io_sdd\" assigned a value but never read" { } { } 0 10036 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Verilog HDL or VHDL warning at de10_top.v(97): object \"io_win\" assigned a value but never read" { } { } 0 10036 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Verilog HDL or VHDL warning at de10_top.v(102): object \"io_sdd\" assigned a value but never read" { } { } 0 10036 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Some pins have incomplete I/O assignments. Refer to the I/O Assignment Warnings report for details" { } { } 0 15714 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "LOCKED port on the PLL is not properly connected on instance \"pll_hdmi:pll_hdmi\|pll_hdmi_0002:pll_hdmi_inst\|altera_pll:altera_pll_i\|general\[0\].gpll\". The LOCKED port on the PLL should be connected when the FBOUTCLK port is connected. Although it is unnecessary to connect the LOCKED signal, any logic driven off of an output clock of the PLL will not know when the PLL is locked and ready." { } { } 0 21300 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "*" { } { } 0 21074 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "RST" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "sysmem_HPS_fpga_interfaces.sdc" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} diff --git a/MacPlus.qpf b/MacPlus.qpf new file mode 100644 index 0000000..9acc2d2 --- /dev/null +++ b/MacPlus.qpf @@ -0,0 +1,32 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 2017 Intel Corporation. All rights reserved. +# Your use of Intel Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Intel Program License +# Subscription Agreement, the Intel Quartus Prime License Agreement, +# the Intel MegaCore Function License Agreement, or other +# applicable license agreement, including, without limitation, +# that your use is for the sole purpose of programming logic +# devices manufactured by Intel and sold by Intel or its +# authorized distributors. Please refer to the applicable +# agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus Prime +# Version 17.0.1 Build 598 06/07/2017 SJ Standard Edition +# Date created = 04:04:47 October 16, 2017 +# +# -------------------------------------------------------------------------- # + +QUARTUS_VERSION = "17.0" +DATE = "04:04:47 October 16, 2017" + +# Revisions + +PROJECT_REVISION = "MacPlus" +PROJECT_REVISION = "MacPlus-lite" diff --git a/MacPlus.qsf b/MacPlus.qsf new file mode 100644 index 0000000..38227d9 --- /dev/null +++ b/MacPlus.qsf @@ -0,0 +1,374 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 2017 Intel Corporation. All rights reserved. +# Your use of Intel Corporation's design tools, logic functions +# and other software and tools, and its AMPP partner logic +# functions, and any output files from any of the foregoing +# (including device programming or simulation files), and any +# associated documentation or information are expressly subject +# to the terms and conditions of the Intel Program License +# Subscription Agreement, the Intel Quartus Prime License Agreement, +# the Intel MegaCore Function License Agreement, or other +# applicable license agreement, including, without limitation, +# that your use is for the sole purpose of programming logic +# devices manufactured by Intel and sold by Intel or its +# authorized distributors. Please refer to the applicable +# agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus Prime +# Version 16.1.2 Build 203 01/18/2017 SJ Standard Edition +# Date created = 01:53:32 April 20, 2017 +# +# -------------------------------------------------------------------------- # + +set_global_assignment -name FAMILY "Cyclone V" +set_global_assignment -name DEVICE 5CSEBA6U23I7 +set_global_assignment -name TOP_LEVEL_ENTITY sys_top +set_global_assignment -name ORIGINAL_QUARTUS_VERSION 16.1.2 +set_global_assignment -name LAST_QUARTUS_VERSION "17.0.1 Standard Edition" +set_global_assignment -name PROJECT_CREATION_TIME_DATE "01:53:30 APRIL 20, 2017" +set_global_assignment -name DEVICE_FILTER_PACKAGE UFBGA +set_global_assignment -name DEVICE_FILTER_PIN_COUNT 672 +set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 7 + +set_global_assignment -name GENERATE_RBF_FILE ON +set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files +set_global_assignment -name NUM_PARALLEL_PROCESSORS ALL +set_global_assignment -name SAVE_DISK_SPACE OFF +set_global_assignment -name SMART_RECOMPILE ON +set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top +set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top +set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top +set_global_assignment -name MIN_CORE_JUNCTION_TEMP "-40" +set_global_assignment -name MAX_CORE_JUNCTION_TEMP 100 +set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW" +set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)" +set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS OFF +set_global_assignment -name OPTIMIZE_POWER_DURING_FITTING OFF +set_global_assignment -name FINAL_PLACEMENT_OPTIMIZATION ALWAYS +set_global_assignment -name FITTER_EFFORT "STANDARD FIT" +set_global_assignment -name OPTIMIZATION_MODE BALANCED +set_global_assignment -name SEED 1 + +#============================================================ +# ADC +#============================================================ +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ADC_CONVST +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ADC_SCK +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ADC_SDI +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ADC_SDO +set_location_assignment PIN_U9 -to ADC_CONVST +set_location_assignment PIN_V10 -to ADC_SCK +set_location_assignment PIN_AC4 -to ADC_SDI +set_location_assignment PIN_AD4 -to ADC_SDO + +#============================================================ +# ARDUINO +#============================================================ +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[6] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[7] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[8] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[9] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[10] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[11] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[12] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[13] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[14] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to ARDUINO_IO[15] +set_location_assignment PIN_AG9 -to ARDUINO_IO[3] +set_location_assignment PIN_U14 -to ARDUINO_IO[4] +set_location_assignment PIN_U13 -to ARDUINO_IO[5] +set_location_assignment PIN_AG8 -to ARDUINO_IO[6] +set_location_assignment PIN_AH8 -to ARDUINO_IO[7] +set_location_assignment PIN_AF17 -to ARDUINO_IO[8] +set_location_assignment PIN_AE15 -to ARDUINO_IO[9] +set_location_assignment PIN_AF15 -to ARDUINO_IO[10] +set_location_assignment PIN_AG16 -to ARDUINO_IO[11] +set_location_assignment PIN_AH11 -to ARDUINO_IO[12] +set_location_assignment PIN_AH12 -to ARDUINO_IO[13] +set_location_assignment PIN_AH9 -to ARDUINO_IO[14] +set_location_assignment PIN_AG11 -to ARDUINO_IO[15] + +#============================================================ +# SDIO +#============================================================ +set_location_assignment PIN_AF25 -to SDIO_DAT[0] +set_location_assignment PIN_AF23 -to SDIO_DAT[1] +set_location_assignment PIN_AD26 -to SDIO_DAT[2] +set_location_assignment PIN_AF28 -to SDIO_DAT[3] +set_location_assignment PIN_AF27 -to SDIO_CMD +set_location_assignment PIN_AH26 -to SDIO_CLK +set_location_assignment PIN_AH7 -to SDIO_CD + +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDIO_* + +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDIO_* +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to SDIO_DAT[*] +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to SDIO_CMD +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to SDIO_CD + +#============================================================ +# VGA +#============================================================ +set_location_assignment PIN_AE17 -to VGA_R[0] +set_location_assignment PIN_AE20 -to VGA_R[1] +set_location_assignment PIN_AF20 -to VGA_R[2] +set_location_assignment PIN_AH18 -to VGA_R[3] +set_location_assignment PIN_AH19 -to VGA_R[4] +set_location_assignment PIN_AF21 -to VGA_R[5] + +set_location_assignment PIN_AE19 -to VGA_G[0] +set_location_assignment PIN_AG15 -to VGA_G[1] +set_location_assignment PIN_AF18 -to VGA_G[2] +set_location_assignment PIN_AG18 -to VGA_G[3] +set_location_assignment PIN_AG19 -to VGA_G[4] +set_location_assignment PIN_AG20 -to VGA_G[5] + +set_location_assignment PIN_AG21 -to VGA_B[0] +set_location_assignment PIN_AA20 -to VGA_B[1] +set_location_assignment PIN_AE22 -to VGA_B[2] +set_location_assignment PIN_AF22 -to VGA_B[3] +set_location_assignment PIN_AH23 -to VGA_B[4] +set_location_assignment PIN_AH21 -to VGA_B[5] + +set_location_assignment PIN_AH22 -to VGA_HS +set_location_assignment PIN_AG24 -to VGA_VS + +set_location_assignment PIN_AH27 -to VGA_EN +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to VGA_EN + +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to VGA_* +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to VGA_* + +#============================================================ +# AUDIO +#============================================================ +set_location_assignment PIN_AC24 -to AUDIO_L +set_location_assignment PIN_AE25 -to AUDIO_R +set_location_assignment PIN_AG26 -to AUDIO_SPDIF +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to AUDIO_* +set_instance_assignment -name CURRENT_STRENGTH_NEW 8MA -to AUDIO_* + +#============================================================ +# SDRAM +#============================================================ +set_location_assignment PIN_Y11 -to SDRAM_A[0] +set_location_assignment PIN_AA26 -to SDRAM_A[1] +set_location_assignment PIN_AA13 -to SDRAM_A[2] +set_location_assignment PIN_AA11 -to SDRAM_A[3] +set_location_assignment PIN_W11 -to SDRAM_A[4] +set_location_assignment PIN_Y19 -to SDRAM_A[5] +set_location_assignment PIN_AB23 -to SDRAM_A[6] +set_location_assignment PIN_AC23 -to SDRAM_A[7] +set_location_assignment PIN_AC22 -to SDRAM_A[8] +set_location_assignment PIN_C12 -to SDRAM_A[9] +set_location_assignment PIN_AB26 -to SDRAM_A[10] +set_location_assignment PIN_AD17 -to SDRAM_A[11] +set_location_assignment PIN_D12 -to SDRAM_A[12] +set_location_assignment PIN_Y17 -to SDRAM_BA[0] +set_location_assignment PIN_AB25 -to SDRAM_BA[1] + +set_location_assignment PIN_E8 -to SDRAM_DQ[0] +set_location_assignment PIN_V12 -to SDRAM_DQ[1] +set_location_assignment PIN_D11 -to SDRAM_DQ[2] +set_location_assignment PIN_W12 -to SDRAM_DQ[3] +set_location_assignment PIN_AH13 -to SDRAM_DQ[4] +set_location_assignment PIN_D8 -to SDRAM_DQ[5] +set_location_assignment PIN_AH14 -to SDRAM_DQ[6] +set_location_assignment PIN_AF7 -to SDRAM_DQ[7] +set_location_assignment PIN_AE24 -to SDRAM_DQ[8] +set_location_assignment PIN_AD23 -to SDRAM_DQ[9] +set_location_assignment PIN_AE6 -to SDRAM_DQ[10] +set_location_assignment PIN_AE23 -to SDRAM_DQ[11] +set_location_assignment PIN_AG14 -to SDRAM_DQ[12] +set_location_assignment PIN_AD5 -to SDRAM_DQ[13] +set_location_assignment PIN_AF4 -to SDRAM_DQ[14] +set_location_assignment PIN_AH3 -to SDRAM_DQ[15] +set_location_assignment PIN_AG13 -to SDRAM_DQML +set_location_assignment PIN_AF13 -to SDRAM_DQMH + +set_location_assignment PIN_AD20 -to SDRAM_CLK +set_location_assignment PIN_AG10 -to SDRAM_CKE + +set_location_assignment PIN_AA19 -to SDRAM_nWE +set_location_assignment PIN_AA18 -to SDRAM_nCAS +set_location_assignment PIN_Y18 -to SDRAM_nCS +set_location_assignment PIN_W14 -to SDRAM_nRAS + +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_* +set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM_* +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_A* +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_BA* +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQ[*] +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQM* +set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_n* +set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM_DQ[*] +set_instance_assignment -name ALLOW_SYNCH_CTRL_USAGE OFF -to *|SDRAM_* + +#============================================================ +# I/O +#============================================================ +set_location_assignment PIN_Y15 -to LED_USER +set_location_assignment PIN_AA15 -to LED_HDD +set_location_assignment PIN_AG28 -to LED_POWER + +set_location_assignment PIN_AH24 -to BTN_USER +set_location_assignment PIN_AG25 -to BTN_OSD +set_location_assignment PIN_AG23 -to BTN_RESET + +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED_* +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to BTN_* +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to BTN_* + +#============================================================ +# CLOCK +#============================================================ +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FPGA_CLK1_50 +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FPGA_CLK2_50 +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to FPGA_CLK3_50 +set_location_assignment PIN_V11 -to FPGA_CLK1_50 +set_location_assignment PIN_Y13 -to FPGA_CLK2_50 +set_location_assignment PIN_E11 -to FPGA_CLK3_50 + +#============================================================ +# HDMI +#============================================================ +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_I2C_SCL +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_I2C_SDA +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_I2S +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_LRCLK +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_MCLK +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_SCLK +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_CLK +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_DE +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[6] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[7] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[8] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[9] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[10] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[11] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[12] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[13] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[14] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[15] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[16] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[17] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[18] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[19] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[20] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[21] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[22] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_D[23] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_HS +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_INT +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HDMI_TX_VS +set_location_assignment PIN_U10 -to HDMI_I2C_SCL +set_location_assignment PIN_AA4 -to HDMI_I2C_SDA +set_location_assignment PIN_T13 -to HDMI_I2S +set_location_assignment PIN_T11 -to HDMI_LRCLK +set_location_assignment PIN_U11 -to HDMI_MCLK +set_location_assignment PIN_T12 -to HDMI_SCLK +set_location_assignment PIN_AG5 -to HDMI_TX_CLK +set_location_assignment PIN_AD19 -to HDMI_TX_DE +set_location_assignment PIN_AD12 -to HDMI_TX_D[0] +set_location_assignment PIN_AE12 -to HDMI_TX_D[1] +set_location_assignment PIN_W8 -to HDMI_TX_D[2] +set_location_assignment PIN_Y8 -to HDMI_TX_D[3] +set_location_assignment PIN_AD11 -to HDMI_TX_D[4] +set_location_assignment PIN_AD10 -to HDMI_TX_D[5] +set_location_assignment PIN_AE11 -to HDMI_TX_D[6] +set_location_assignment PIN_Y5 -to HDMI_TX_D[7] +set_location_assignment PIN_AF10 -to HDMI_TX_D[8] +set_location_assignment PIN_Y4 -to HDMI_TX_D[9] +set_location_assignment PIN_AE9 -to HDMI_TX_D[10] +set_location_assignment PIN_AB4 -to HDMI_TX_D[11] +set_location_assignment PIN_AE7 -to HDMI_TX_D[12] +set_location_assignment PIN_AF6 -to HDMI_TX_D[13] +set_location_assignment PIN_AF8 -to HDMI_TX_D[14] +set_location_assignment PIN_AF5 -to HDMI_TX_D[15] +set_location_assignment PIN_AE4 -to HDMI_TX_D[16] +set_location_assignment PIN_AH2 -to HDMI_TX_D[17] +set_location_assignment PIN_AH4 -to HDMI_TX_D[18] +set_location_assignment PIN_AH5 -to HDMI_TX_D[19] +set_location_assignment PIN_AH6 -to HDMI_TX_D[20] +set_location_assignment PIN_AG6 -to HDMI_TX_D[21] +set_location_assignment PIN_AF9 -to HDMI_TX_D[22] +set_location_assignment PIN_AE8 -to HDMI_TX_D[23] +set_location_assignment PIN_T8 -to HDMI_TX_HS +set_location_assignment PIN_AF11 -to HDMI_TX_INT +set_location_assignment PIN_V13 -to HDMI_TX_VS + +#============================================================ +# KEY +#============================================================ +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to KEY[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to KEY[1] +set_location_assignment PIN_AH17 -to KEY[0] +set_location_assignment PIN_AH16 -to KEY[1] + +#============================================================ +# LED +#============================================================ +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[3] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[4] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[5] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[6] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[7] +set_location_assignment PIN_W15 -to LED[0] +set_location_assignment PIN_AA24 -to LED[1] +set_location_assignment PIN_V16 -to LED[2] +set_location_assignment PIN_V15 -to LED[3] +set_location_assignment PIN_AF26 -to LED[4] +set_location_assignment PIN_AE26 -to LED[5] +set_location_assignment PIN_Y16 -to LED[6] +set_location_assignment PIN_AA23 -to LED[7] + +#============================================================ +# SW +#============================================================ +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[0] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[1] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[2] +set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[3] +set_location_assignment PIN_Y24 -to SW[0] +set_location_assignment PIN_W24 -to SW[1] +set_location_assignment PIN_W21 -to SW[2] +set_location_assignment PIN_W20 -to SW[3] + +set_global_assignment -name PRE_FLOW_SCRIPT_FILE "quartus_sh:sys/build_id.tcl" + +set_global_assignment -name CDF_FILE jtag.cdf +set_global_assignment -name QIP_FILE sys/sys.qip +set_global_assignment -name QIP_FILE sys/vip.qip +set_global_assignment -name VERILOG_FILE scsi.v +set_global_assignment -name VERILOG_FILE ncr5380.v +set_global_assignment -name VERILOG_FILE floppy_track_encoder.v +set_global_assignment -name VERILOG_FILE floppy.v +set_global_assignment -name SYSTEMVERILOG_FILE ps2_kbd.sv +set_global_assignment -name VERILOG_FILE ps2_mouse.v +set_global_assignment -name VHDL_FILE TG68K_Pack.vhd +set_global_assignment -name VHDL_FILE TG68K_ALU.vhd +set_global_assignment -name VHDL_FILE TG68KdotC_Kernel.vhd +set_global_assignment -name VERILOG_FILE scc.v +set_global_assignment -name VERILOG_FILE iwm.v +set_global_assignment -name VERILOG_FILE via.v +set_global_assignment -name VERILOG_FILE addrDecoder.v +set_global_assignment -name VERILOG_FILE addrController_top.v +set_global_assignment -name VERILOG_FILE dataController_top.v +set_global_assignment -name VERILOG_FILE video.v +set_global_assignment -name SYSTEMVERILOG_FILE MacPlus.sv +set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/MacPlus.srf b/MacPlus.srf new file mode 100644 index 0000000..04c03cc --- /dev/null +++ b/MacPlus.srf @@ -0,0 +1,51 @@ +{ "" "" "" "Variable or input pin \"data_b\" is defined but never used." { } { } 0 287013 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Found combinational loop of 47 nodes" { } { } 0 332125 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "LOCKED port on the PLL is not properly connected on instance \"pll_hdmi:pll_hdmi\|pll_hdmi_0002:pll_hdmi_inst\|altera_pll:altera_pll_i\|general\[0\].gpll\". The LOCKED port on the PLL should be connected when the FBOUTCLK port is connected. Although it is unnecessary to connect the LOCKED signal, any logic driven off of an output clock of the PLL will not know when the PLL is locked and ready." { } { } 0 21300 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Net \"soc_system:soc_system\|soc_system_Video_Output:video_output\|alt_vip_cvo_core:cvo_core\|genlock_enable_sync1\[1\]\" is missing source, defaulting to GND" { } { } 0 12110 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Inferred RAM node \"zxspectrum:emu\|mist_io:mist_io\|ps2_kbd_fifo_rtl_0\" from synchronous design logic. Pass-through logic has been added to match the read-during-write behavior of the original design." { } { } 0 276020 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Inferred RAM node \"zxspectrum:emu\|mist_io:mist_io\|ps2_mouse_fifo_rtl_0\" from synchronous design logic. Pass-through logic has been added to match the read-during-write behavior of the original design." { } { } 0 276020 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "No destination clock period was found satisfying the set_net_delay assignment from \"\[get_keepers \{soc_system\|video_output\|cvo_core\|mode_banks\|h_sync_polarity_reg\}\]\" to \"\[get_keepers \{soc_system\|video_output\|cvo_core\|mode_banks\|vid_h_sync_polarity\}\]\". This assignment will be ignored." { } { } 0 17897 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "No destination clock period was found satisfying the set_net_delay assignment from \"\[get_keepers \{soc_system\|video_output\|cvo_core\|mode_banks\|v_sync_polarity_reg\}\]\" to \"\[get_keepers \{soc_system\|video_output\|cvo_core\|mode_banks\|vid_v_sync_polarity\}\]\". This assignment will be ignored." { } { } 0 17897 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "No destination clock period was found satisfying the set_net_delay assignment from \"\[get_keepers \{soc_system\|video_output\|cvo_core\|mode_banks\|interlaced_field_reg\[*\]\}\]\" to \"\[get_keepers \{soc_system\|video_output\|cvo_core\|mode_banks\|vid_interlaced_field\[*\]\}\]\". This assignment will be ignored." { } { } 0 17897 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Some pins have incomplete I/O assignments. Refer to the I/O Assignment Warnings report for details" { } { } 0 15714 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "55 hierarchies have connectivity warnings - see the Connectivity Checks report folder" { } { } 0 12241 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Inferred RAM node \"emu:emu\|mister_io:mister_io\|ps2_kbd_fifo_rtl_0\" from synchronous design logic. Pass-through logic has been added to match the read-during-write behavior of the original design." { } { } 0 276020 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Inferred RAM node \"emu:emu\|mister_io:mister_io\|ps2_mouse_fifo_rtl_0\" from synchronous design logic. Pass-through logic has been added to match the read-during-write behavior of the original design." { } { } 0 276020 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Verilog HDL or VHDL warning at de10_top.v(97): object \"io_win\" assigned a value but never read" { } { } 0 10036 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Verilog HDL or VHDL warning at de10_top.v(102): object \"io_sdd\" assigned a value but never read" { } { } 0 10036 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Overwriting existing clock: vip\|hps\|fpga_interfaces\|clocks_resets\|h2f_user0_clk" { } { } 0 332043 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "Variable or input pin \"data_a\" is defined but never used." { } { } 0 287013 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "*" { } { } 0 169085 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "*" { } { } 0 174073 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "*" { } { } 0 332174 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "*" { } { } 0 13009 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "*" { } { } 0 21300 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "alt_vip_cvo_mode_banks" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "hps_sdram_pll.sv" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "alt_vip_common_frame_counter.v" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "hps_sdram_p0_acv_hard_memphy.v" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "hps_sdram_p0_acv_ldc.v" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "hps_sdram_p0_acv_hard_io_pads.v" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "altera_mem_if_hard_memory_controller_top_cyclonev.sv" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "genlock_enable_sync" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "u_calculate_mode" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "genlock_enable" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "reset_value" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "soc_system:soc_system\|soc_system_pll_video:pll_video\|altera_pll:altera_pll_i\|general\[0\].gpll" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "alt_vip_cvo_core.sdc" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "alt_vip_packet_transfer.sdc" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "hps_sdram_p0.sdc" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "alt_vip_common_dc_mixed_widths_fifo.sdc" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "altera_mem_if_hhp_qseq_synth_top" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "soc_system:soc_system\|soc_system_vip_vout:vip_vout\|alt_vip_cvo_core:cvo_core\|genlock_enable_sync1" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "soc_system:soc_system\|soc_system_vip_fb:vip_fb\|alt_vip_packet_transfer:pkt_trans_rd\|alt_vip_packet_transfer_read_proc:READ_BLOCK.read_proc_instance\|alt_vip_common_fifo2:output_msg_queue\|scfifo:scfifo_component\|scfifo_scd1:auto_generated\|a_dpfifo_e471:dpfifo\|altsyncram_ums1:FIFOram\|q_b" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "soc_system:soc_system\|soc_system_Video_Input:video_input\|alt_vip_cvi_core:cvi_core\|alt_vip_cvi_write_fifo_buffer:write_fifo_buffer" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "soc_system:soc_system\|soc_system_Frame_Buffer:frame_buffer\|alt_vip_packet_transfer:pkt_trans_rd" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "soc_system_hps_fpga_interfaces.sdc" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "soc_system_HPS_fpga_interfaces.sdc" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "RST" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "alt_vip_scaler_alg_core" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "cvo_core" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "vip_HPS_fpga_interfaces.sdc" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "alt_vip_dil_vof_scheduler.sdc" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} +{ "" "" "" "alt_vip_dil_scheduler.sdc" { } { } 0 9999 "" 0 0 "Design Software" 0 -1 0 ""} diff --git a/MacPlus.sv b/MacPlus.sv new file mode 100644 index 0000000..fcd70a6 --- /dev/null +++ b/MacPlus.sv @@ -0,0 +1,574 @@ +//============================================================================ +// Macintosh Plus +// +// Port to MiSTer +// Copyright (C) 2017 Sorgelig +// +// 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. +//============================================================================ + +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 [43: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. + output [7:0] VIDEO_ARX, + output [7: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 LED_USER, // 1 - ON, 0 - OFF. + + // b[1]: 0 - LED status is system status ORed 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, + + output [15:0] AUDIO_L, + output [15:0] AUDIO_R, + output AUDIO_S, // 1 - signed audio samples, 0 - unsigned + input TAPE_IN, + + // SD-SPI + output SD_SCK, + output SD_MOSI, + input SD_MISO, + output SD_CS, + + //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 +); + +assign {DDRAM_CLK, DDRAM_BURSTCNT, DDRAM_ADDR, DDRAM_DIN, DDRAM_BE, DDRAM_RD, DDRAM_WE} = 0; +assign {SD_SCK, SD_MOSI, SD_CS} = 'Z; + +assign LED_USER = dio_download || (disk_act ^ |diskMotor); +assign LED_DISK = 0; +assign LED_POWER = 0; + +assign VIDEO_ARX = status[8] ? 8'd16 : 8'd4; +assign VIDEO_ARY = status[8] ? 8'd9 : 8'd3; + +`include "build_id.v" +localparam CONF_STR = { + "MACPLUS;;", + "-;", + "F,DSK;", + "F,DSK;", + "S,VHD;", + "-;", + "O8,Aspect ratio,4:3,16:9;", + "-;", + "O9A,Memory,512KB,1MB,4MB;", + "O5,Speed,Normal,Turbo;", + "-;", + "T6,Reset;", + "V,v1.00.",`BUILD_DATE +}; + +//////////////////// CLOCKS /////////////////// + +wire clk_sys; +wire pll_locked; + +pll pll +( + .refclk(CLK_50M), + .rst(0), + .outclk_0(clk_sys), + .outclk_1(SDRAM_CLK), + .locked(pll_locked) +); + +wire cep = (stage == 0); +wire cen = (stage == 4); +wire cel = (stage == 7); +wire cepix = !stage[1:0]; + +reg [2:0] stage; +always @(negedge clk_sys) stage <= stage + 1'd1; + +/////////////////////////////////////////////////// + +// interconnects +// CPU +wire _cpuReset, _cpuResetOut, _cpuUDS, _cpuLDS, _cpuRW; +wire [2:0] _cpuIPL; +wire [7:0] cpuAddrHi; +wire [23:0] cpuAddr; +wire [15:0] cpuDataOut; + +// RAM/ROM +wire _romOE; +wire _ramOE, _ramWE; +wire _memoryUDS, _memoryLDS; +wire videoBusControl; +wire dioBusControl; +wire cpuBusControl; +wire [21:0] memoryAddr; +wire [15:0] memoryDataOut; + +// peripherals +wire memoryOverlayOn, selectSCSI, selectSCC, selectIWM, selectVIA; +wire [15:0] dataControllerDataOut; + +// audio +wire snd_alt; +wire loadSound; + +// floppy disk image interface +wire dskReadAckInt; +wire [21:0] dskReadAddrInt; +wire dskReadAckExt; +wire [21:0] dskReadAddrExt; +wire [1:0] diskMotor, diskAct, diskEject; + +// the status register is controlled by the on screen display (OSD) +wire [31:0] status; +wire [1:0] buttons; +wire [31:0] sd_lba; +wire sd_rd; +wire sd_wr; +wire sd_ack; +wire [8:0] sd_buff_addr; +wire [7:0] sd_buff_dout; +wire [7:0] sd_buff_din; +wire sd_buff_wr; + +wire ioctl_wr; +reg ioctl_wait = 0; + +wire [64:0] ps2_key; +wire [24:0] ps2_mouse; +wire capslock; + +hps_io #(.STRLEN($size(CONF_STR)>>3)) hps_io +( + .clk_sys(clk_sys), + .HPS_BUS(HPS_BUS), + + .conf_str(CONF_STR), + + .buttons(buttons), + .status(status), + + .sd_lba(sd_lba), + .sd_rd(sd_rd), + .sd_wr(sd_wr), + .sd_ack(sd_ack), + + .sd_conf(0), + .sd_buff_addr(sd_buff_addr), + .sd_buff_dout(sd_buff_dout), + .sd_buff_din(sd_buff_din), + .sd_buff_wr(sd_buff_wr), + + .ioctl_download(dio_download), + .ioctl_index(dio_index), + .ioctl_wr(ioctl_wr), + .ioctl_addr(dio_addr), + .ioctl_dout(dio_data), + + .ioctl_wait(ioctl_wait), + + .ps2_key(ps2_key), + .ps2_kbd_led_use(3'b001), + .ps2_kbd_led_status({2'b00, capslock}), + + .ps2_mouse(ps2_mouse) +); + +wire [1:0] cpu_busstate; +wire cpu_clkena = cep && (cpuBusControl || (cpu_busstate == 2'b01)); +reg [15:0] cpuDataIn; +always @(posedge clk_sys) if(cel && cpuBusControl && ~cpu_busstate[0] && _cpuRW) cpuDataIn <= dataControllerDataOut; + +TG68KdotC_Kernel #(0,0,0,0,0,0) m68k +( + .clk ( clk_sys ), + .nReset ( _cpuReset ), + .clkena_in ( cpu_clkena ), + .data_in ( cpuDataIn ), + .IPL ( _cpuIPL ), + .IPL_autovector ( 1'b1 ), + .berr ( 1'b0 ), + .clr_berr ( 1'b0 ), + .CPU ( 2'b00 ), // 00=68000 + .addr ( {cpuAddrHi, cpuAddr} ), + .data_write ( cpuDataOut ), + .nUDS ( _cpuUDS ), + .nLDS ( _cpuLDS ), + .nWr ( _cpuRW ), + .busstate ( cpu_busstate ), // 00-> fetch code 10->read data 11->write data 01->no memaccess + .nResetOut ( _cpuResetOut ), + .FC ( ) +); + +assign VGA_R = {8{pixelOut}}; +assign VGA_G = {8{pixelOut}}; +assign VGA_B = {8{pixelOut}}; +assign CLK_VIDEO = clk_sys; +assign CE_PIXEL = cepix; + +wire screenWrite; +always @(*) begin + case(configRAMSize) + 0: screenWrite = ~_ramWE && &memoryAddr[16:15]; // 01A700 (018000) + 1: screenWrite = ~_ramWE && &memoryAddr[18:15]; // 07A700 (078000) + 2: screenWrite = ~_ramWE && &memoryAddr[19:15]; // 0FA700 (0F8000) + 3: screenWrite = ~_ramWE && &memoryAddr[21:15]; // 3FA700 (3F8000) + endcase +end + +wire pixelOut, _hblank, _vblank; +video video +( + .clk(clk_sys), + .ce(cepix), + + .addr(cpuAddr[15:1]), + .dataIn(cpuDataOut), + .wr({~_cpuUDS & screenWrite, ~_cpuLDS & screenWrite}), + + ._hblank(_hblank), + ._vblank(_vblank), + + .hsync(VGA_HS), + .vsync(VGA_VS), + .video_en(VGA_DE), + .pixelOut(pixelOut) +); + +wire [10:0] audio; +assign AUDIO_L = {audio[10:0], 5'b00000}; +assign AUDIO_R = {audio[10:0], 5'b00000}; +assign AUDIO_S = 0; + +wire status_turbo = status[5]; +wire status_reset = status[6]; + +wire [1:0] status_mem = status[10:9]; // 128KB, 512KB, 1MB, 4MB +reg [1:0] configRAMSize= 3; + +reg n_reset = 0; +always @(posedge clk_sys) begin + reg [15:0] rst_cnt; + + // various sources can reset the mac + if(!pll_locked || status[0] || status_reset || buttons[1] || RESET || ~_cpuResetOut) begin + rst_cnt <= '1; + n_reset <= 0; + end else if(rst_cnt) begin + if(cen) rst_cnt <= rst_cnt - 1'd1; + configRAMSize <= status_mem + 1'd1; + end else n_reset <= 1; +end + +addrController_top ac0 +( + .clk(clk_sys), + .cep(cep), + .cen(cen), + + .cpuAddr(cpuAddr), + ._cpuUDS(_cpuUDS), + ._cpuLDS(_cpuLDS), + ._cpuRW(_cpuRW), + .turbo(real_turbo), + .configROMSize(1), // 128KB + .configRAMSize(configRAMSize), + .memoryAddr(memoryAddr), + ._memoryUDS(_memoryUDS), + ._memoryLDS(_memoryLDS), + ._romOE(_romOE), + ._ramOE(_ramOE), + ._ramWE(_ramWE), + .dioBusControl(dioBusControl), + .cpuBusControl(cpuBusControl), + .selectSCSI(selectSCSI), + .selectSCC(selectSCC), + .selectIWM(selectIWM), + .selectVIA(selectVIA), + ._vblank(_vblank), + ._hblank(_hblank), + .memoryOverlayOn(memoryOverlayOn), + + .snd_alt(snd_alt), + .loadSound(loadSound), + + .dskReadAddrInt(dskReadAddrInt), + .dskReadAckInt(dskReadAckInt), + .dskReadAddrExt(dskReadAddrExt), + .dskReadAckExt(dskReadAckExt) +); + +dataController_top dc0 +( + .clk(clk_sys), + .cep(cep), + .cen(cen), + + ._systemReset(n_reset), + ._cpuReset(_cpuReset), + ._cpuIPL(_cpuIPL), + ._cpuUDS(_cpuUDS), + ._cpuLDS(_cpuLDS), + ._cpuRW(_cpuRW), + .cpuDataIn(cpuDataOut), + .cpuDataOut(dataControllerDataOut), + .cpuAddrRegHi(cpuAddr[12:9]), + .cpuAddrRegMid(cpuAddr[6:4]), // for SCSI + .cpuAddrRegLo(cpuAddr[2:1]), + .selectSCSI(selectSCSI), + .selectSCC(selectSCC), + .selectIWM(selectIWM), + .selectVIA(selectVIA), + .cpuBusControl(cpuBusControl), + .memoryDataOut(memoryDataOut), + .memoryDataIn(sdram_do), + + // peripherals + .ps2_key(ps2_key), + .capslock(capslock), + .ps2_mouse(ps2_mouse), + .serialIn(0), + + // video + ._hblank(_hblank), + ._vblank(_vblank), + + .memoryOverlayOn(memoryOverlayOn), + + .audioOut(audio), + .snd_alt(snd_alt), + .loadSound(loadSound), + + // floppy disk interface + .insertDisk({dsk_ext_ins, dsk_int_ins}), + .diskSides({dsk_ext_ds, dsk_int_ds}), + .diskEject(diskEject), + .dskReadAddrInt(dskReadAddrInt), + .dskReadAckInt(dskReadAckInt), + .dskReadAddrExt(dskReadAddrExt), + .dskReadAckExt(dskReadAckExt), + + .diskMotor(diskMotor), + .diskAct(diskAct), + + // block device interface for scsi disk + .io_lba(sd_lba), + .io_rd(sd_rd), + .io_wr(sd_wr), + .io_ack(sd_ack), + + .sd_buff_addr(sd_buff_addr), + .sd_buff_dout(sd_buff_dout), + .sd_buff_din(sd_buff_din), + .sd_buff_wr(sd_buff_wr) +); + +reg disk_act; +always @(posedge clk_sys) begin + integer timeout = 0; + + if(timeout) begin + timeout <= timeout - 1; + disk_act <= 1; + end else begin + disk_act <= 0; + end + + if(|diskAct) timeout <= 1000000; +end + +//////////////////////// DOWNLOADING /////////////////////////// + +// include ROM download helper +wire dio_download; +reg dio_write; +wire [23:0] dio_addr; +wire [7:0] dio_index; +wire [15:0] dio_data; + +// good floppy image sizes are 819200 bytes and 409600 bytes +reg dsk_int_ds, dsk_ext_ds; // double sided image inserted +reg dsk_int_ss, dsk_ext_ss; // single sided image inserted + +// any known type of disk image inserted? +wire dsk_int_ins = dsk_int_ds || dsk_int_ss; +wire dsk_ext_ins = dsk_ext_ds || dsk_ext_ss; + +// at the end of a download latch file size +// diskEject is set by macos on eject +always @(posedge clk_sys) begin + reg old_down; + + old_down <= dio_download; + if(old_down && ~dio_download && dio_index == 1) begin + dsk_int_ds <= (dio_addr == 409600); // double sides disk, addr counts words, not bytes + dsk_int_ss <= (dio_addr == 204800); // single sided disk + end + + if(diskEject[0]) begin + dsk_int_ds <= 0; + dsk_int_ss <= 0; + end +end + +always @(posedge clk_sys) begin + reg old_down; + + old_down <= dio_download; + if(old_down && ~dio_download && dio_index == 2) begin + dsk_ext_ds <= (dio_addr == 409600); // double sided disk, addr counts words, not bytes + dsk_ext_ss <= (dio_addr == 204800); // single sided disk + end + + if(diskEject[1]) begin + dsk_ext_ds <= 0; + dsk_ext_ss <= 0; + end +end + +// disk images are being stored right after os rom at word offset 0x80000 and 0x100000 +wire [20:0] dio_a = + (dio_index == 0)?dio_addr[20:0]: // os rom + (dio_index == 1)?{21'h80000 + dio_addr[20:0]}: // first dsk image at 512k word addr + {21'h100000 + dio_addr[20:0]}; // second dsk image at 1M word addr + +always @(posedge clk_sys) begin + reg old_cyc = 0; + + old_cyc <= dioBusControl; + if(ioctl_wr) ioctl_wait <= 1; + + if(~dioBusControl) dio_write <= ioctl_wait; + if(old_cyc & ~dioBusControl & dio_write) ioctl_wait <= 0; +end + +// sdram used for ram/rom maps directly into 68k address space +wire download_cycle = dio_download && dioBusControl; + +////////////////////////// SDRAM ///////////////////////////////// + +wire [24:0] sdram_addr = download_cycle ? { 4'b0001, dio_a[20:0] } : { 3'b000, ~_romOE, memoryAddr[21:1] }; +wire [15:0] sdram_din = download_cycle ? dio_data : memoryDataOut; +wire [1:0] sdram_ds = download_cycle ? 2'b11 : { !_memoryUDS, !_memoryLDS }; +wire sdram_we = download_cycle ? dio_write : !_ramWE; +wire sdram_oe = download_cycle ? 1'b0 : (!_ramOE || !_romOE); +wire [15:0] sdram_do = download_cycle ? 16'hffff : (dskReadAckInt || dskReadAckExt) ? extra_rom_data_demux : sdram_out; + +// "extra rom" is used to hold the disk image. It's expected to be byte wide and +// we thus need to properly demultiplex the word returned from sdram in that case +wire [15:0] extra_rom_data_demux = memoryAddr[0]? {sdram_out[7:0],sdram_out[7:0]}:{sdram_out[15:8],sdram_out[15:8]}; +wire [15:0] sdram_out; + +assign SDRAM_CKE = 1; + +sdram sdram +( + // system interface + .init ( !pll_locked ), + .clk ( clk_sys ), + .sync ( cep ), + + // interface to the MT48LC16M16 chip + .sd_data ( SDRAM_DQ ), + .sd_addr ( SDRAM_A ), + .sd_dqm ( {SDRAM_DQMH, SDRAM_DQML} ), + .sd_cs ( SDRAM_nCS ), + .sd_ba ( SDRAM_BA ), + .sd_we ( SDRAM_nWE ), + .sd_ras ( SDRAM_nRAS ), + .sd_cas ( SDRAM_nCAS ), + + // cpu/chipset interface + // map rom to sdram word address $200000 - $20ffff + .din ( sdram_din ), + .addr ( sdram_addr ), + .ds ( sdram_ds ), + .we ( sdram_we ), + .oe ( sdram_oe ), + .dout ( sdram_out ) +); + + +//////////////////////// TURBO HANDLING ////////////////////////// + +// cannot boot from SCSI if turbo enabled +// delay the turbo. +reg real_turbo = 0; +always @(posedge clk_sys) begin + reg old_ack; + integer ack_cnt = 0; + + old_ack <= sd_ack; + if(old_ack && ~sd_ack && ack_cnt) ack_cnt <= ack_cnt - 1'd1; + + //Cancel delay if FDD is accesed. + if(diskMotor) ack_cnt <= 0; + if(!ack_cnt && dioBusControl) real_turbo <= status_turbo; + + if(~n_reset) begin + real_turbo <= 0; + ack_cnt <= 20; + end +end + +endmodule diff --git a/TG68K_ALU.vhd b/TG68K_ALU.vhd new file mode 100644 index 0000000..dceb2c7 --- /dev/null +++ b/TG68K_ALU.vhd @@ -0,0 +1,932 @@ +------------------------------------------------------------------------------ +------------------------------------------------------------------------------ +-- -- +-- Copyright (c) 2009-2011 Tobias Gubener -- +-- Subdesign fAMpIGA by TobiFlex -- +-- -- +-- This source file 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 3 of the License, or -- +-- (at your option) any later version. -- +-- -- +-- This source file 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, see . -- +-- -- +------------------------------------------------------------------------------ +------------------------------------------------------------------------------ + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; +use IEEE.numeric_std.all; +use work.TG68K_Pack.all; + +entity TG68K_ALU is +generic( + MUL_Mode : integer := 0; --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no MUL, + DIV_Mode : integer := 0 --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no DIV, + ); + port(clk : in std_logic; + Reset : in std_logic; + clkena_lw : in std_logic:='1'; + execOPC : in bit; + exe_condition : in std_logic; + exec_tas : in std_logic; + long_start : in bit; + movem_presub : in bit; + set_stop : in bit; + Z_error : in bit; + rot_bits : in std_logic_vector(1 downto 0); + exec : in bit_vector(lastOpcBit downto 0); + OP1out : in std_logic_vector(31 downto 0); + OP2out : in std_logic_vector(31 downto 0); + reg_QA : in std_logic_vector(31 downto 0); + reg_QB : in std_logic_vector(31 downto 0); + opcode : in std_logic_vector(15 downto 0); + datatype : in std_logic_vector(1 downto 0); + exe_opcode : in std_logic_vector(15 downto 0); + exe_datatype : in std_logic_vector(1 downto 0); + sndOPC : in std_logic_vector(15 downto 0); + last_data_read : in std_logic_vector(15 downto 0); + data_read : in std_logic_vector(15 downto 0); + FlagsSR : in std_logic_vector(7 downto 0); + micro_state : in micro_states; + bf_ext_in : in std_logic_vector(7 downto 0); + bf_ext_out : out std_logic_vector(7 downto 0); + bf_shift : in std_logic_vector(5 downto 0); + bf_width : in std_logic_vector(5 downto 0); + bf_loffset : in std_logic_vector(4 downto 0); + + set_V_Flag : buffer bit; + Flags : buffer std_logic_vector(7 downto 0); + c_out : buffer std_logic_vector(2 downto 0); + addsub_q : buffer std_logic_vector(31 downto 0); + ALUout : out std_logic_vector(31 downto 0) + ); +end TG68K_ALU; + +architecture logic of TG68K_ALU is +----------------------------------------------------------------------------- +----------------------------------------------------------------------------- +-- ALU and more +----------------------------------------------------------------------------- +----------------------------------------------------------------------------- + signal OP1in : std_logic_vector(31 downto 0); + signal addsub_a : std_logic_vector(31 downto 0); + signal addsub_b : std_logic_vector(31 downto 0); + signal notaddsub_b : std_logic_vector(33 downto 0); + signal add_result : std_logic_vector(33 downto 0); + signal addsub_ofl : std_logic_vector(2 downto 0); + signal opaddsub : bit; + signal c_in : std_logic_vector(3 downto 0); + signal flag_z : std_logic_vector(2 downto 0); + signal set_Flags : std_logic_vector(3 downto 0); --NZVC + signal CCRin : std_logic_vector(7 downto 0); + + signal niba_l : std_logic_vector(5 downto 0); + signal niba_h : std_logic_vector(5 downto 0); + signal niba_lc : std_logic; + signal niba_hc : std_logic; + signal bcda_lc : std_logic; + signal bcda_hc : std_logic; + signal nibs_l : std_logic_vector(5 downto 0); + signal nibs_h : std_logic_vector(5 downto 0); + signal nibs_lc : std_logic; + signal nibs_hc : std_logic; + + signal bcd_a : std_logic_vector(8 downto 0); + signal bcd_s : std_logic_vector(8 downto 0); + signal pack_out : std_logic_vector(15 downto 0); + signal pack_a : std_logic_vector(15 downto 0); + signal result_mulu : std_logic_vector(63 downto 0); + signal result_div : std_logic_vector(63 downto 0); + signal set_mV_Flag : std_logic; + signal V_Flag : bit; + + signal rot_rot : std_logic; + signal rot_lsb : std_logic; + signal rot_msb : std_logic; + signal rot_X : std_logic; + signal rot_C : std_logic; + signal rot_out : std_logic_vector(31 downto 0); + signal asl_VFlag : std_logic; + signal bit_bits : std_logic_vector(1 downto 0); + signal bit_number : std_logic_vector(4 downto 0); + signal bits_out : std_logic_vector(31 downto 0); + signal one_bit_in : std_logic; + signal bchg : std_logic; + signal bset : std_logic; + + signal mulu_sign : std_logic; + signal mulu_signext : std_logic_vector(16 downto 0); + signal muls_msb : std_logic; + signal mulu_reg : std_logic_vector(63 downto 0); + signal FAsign : std_logic; + signal faktorA : std_logic_vector(31 downto 0); + signal faktorB : std_logic_vector(31 downto 0); + + signal div_reg : std_logic_vector(63 downto 0); + signal div_quot : std_logic_vector(63 downto 0); + signal div_ovl : std_logic; + signal div_neg : std_logic; + signal div_bit : std_logic; + signal div_sub : std_logic_vector(32 downto 0); + signal div_over : std_logic_vector(32 downto 0); + signal nozero : std_logic; + signal div_qsign : std_logic; + signal divisor : std_logic_vector(63 downto 0); + signal divs : std_logic; + signal signedOP : std_logic; + signal OP1_sign : std_logic; + signal OP2_sign : std_logic; + signal OP2outext : std_logic_vector(15 downto 0); + + signal in_offset : std_logic_vector(5 downto 0); +-- signal in_width : std_logic_vector(5 downto 0); + signal datareg : std_logic_vector(31 downto 0); + signal insert : std_logic_vector(31 downto 0); +-- signal bf_result : std_logic_vector(31 downto 0); +-- signal bf_offset : std_logic_vector(5 downto 0); +-- signal bf_width : std_logic_vector(5 downto 0); +-- signal bf_firstbit : std_logic_vector(5 downto 0); + signal bf_datareg : std_logic_vector(31 downto 0); +-- signal bf_out : std_logic_vector(31 downto 0); + signal result : std_logic_vector(39 downto 0); + signal result_tmp : std_logic_vector(39 downto 0); + signal sign : std_logic_vector(31 downto 0); + signal bf_set1 : std_logic_vector(39 downto 0); + signal inmux0 : std_logic_vector(39 downto 0); + signal inmux1 : std_logic_vector(39 downto 0); + signal inmux2 : std_logic_vector(39 downto 0); + signal inmux3 : std_logic_vector(31 downto 0); + signal copymux0 : std_logic_vector(39 downto 0); + signal copymux1 : std_logic_vector(39 downto 0); + signal copymux2 : std_logic_vector(39 downto 0); + signal copymux3 : std_logic_vector(31 downto 0); + signal bf_set2 : std_logic_vector(31 downto 0); +-- signal bf_set3 : std_logic_vector(31 downto 0); + signal shift : std_logic_vector(39 downto 0); + signal copy : std_logic_vector(39 downto 0); +-- signal offset : std_logic_vector(5 downto 0); +-- signal width : std_logic_vector(5 downto 0); + signal bf_firstbit : std_logic_vector(5 downto 0); + signal mux : std_logic_vector(3 downto 0); + signal bitnr : std_logic_vector(4 downto 0); + signal mask : std_logic_vector(31 downto 0); + signal bf_bset : std_logic; + signal bf_NFlag : std_logic; + signal bf_bchg : std_logic; + signal bf_ins : std_logic; + signal bf_exts : std_logic; + signal bf_fffo : std_logic; + signal bf_d32 : std_logic; + signal bf_s32 : std_logic; + signal index : std_logic_vector(4 downto 0); +-- signal i : integer range 0 to 31; +-- signal i : integer range 0 to 31; +-- signal i : std_logic_vector(5 downto 0); +BEGIN +----------------------------------------------------------------------------- +-- set OP1in +----------------------------------------------------------------------------- +PROCESS (OP2out, reg_QB, opcode, OP1out, OP1in, exe_datatype, addsub_q, execOPC, exec, + pack_out, bcd_a, bcd_s, result_mulu, result_div, exe_condition, bf_shift, + Flags, FlagsSR, bits_out, exec_tas, rot_out, exe_opcode, result, bf_fffo, bf_firstbit, bf_datareg) + BEGIN + ALUout <= OP1in; + ALUout(7) <= OP1in(7) OR exec_tas; + IF exec(opcBFwb)='1' THEN + ALUout <= result(31 downto 0); + IF bf_fffo='1' THEN + ALUout <= (OTHERS =>'0'); + ALUout(5 downto 0) <= bf_firstbit + bf_shift; + END IF; + END IF; + + OP1in <= addsub_q; + IF exec(opcABCD)='1' THEN + OP1in(7 downto 0) <= bcd_a(7 downto 0); + ELSIF exec(opcSBCD)='1' THEN + OP1in(7 downto 0) <= bcd_s(7 downto 0); + ELSIF exec(opcMULU)='1' AND MUL_Mode/=3 THEN + IF exec(write_lowlong)='1' AND (MUL_Mode=1 OR MUL_Mode=2) THEN + OP1in <= result_mulu(31 downto 0); + ELSE + OP1in <= result_mulu(63 downto 32); + END IF; + ELSIF exec(opcDIVU)='1' AND DIV_Mode/=3 THEN + IF exe_opcode(15)='1' OR DIV_Mode=0 THEN +-- IF exe_opcode(15)='1' THEN + OP1in <= result_div(47 downto 32)&result_div(15 downto 0); + ELSE --64bit + IF exec(write_reminder)='1' THEN + OP1in <= result_div(63 downto 32); + ELSE + OP1in <= result_div(31 downto 0); + END IF; + END IF; + ELSIF exec(opcOR)='1' THEN + OP1in <= OP2out OR OP1out; + ELSIF exec(opcAND)='1' THEN + OP1in <= OP2out AND OP1out; + ELSIF exec(opcScc)='1' THEN + OP1in(7 downto 0) <= (others=>exe_condition); + ELSIF exec(opcEOR)='1' THEN + OP1in <= OP2out XOR OP1out; + ELSIF exec(opcMOVE)='1' OR exec(exg)='1' THEN +-- OP1in <= OP2out(31 downto 8)&(OP2out(7)OR exec_tas)&OP2out(6 downto 0); + OP1in <= OP2out; + ELSIF exec(opcROT)='1' THEN + OP1in <= rot_out; + ELSIF exec(opcSWAP)='1' THEN + OP1in <= OP1out(15 downto 0)& OP1out(31 downto 16); + ELSIF exec(opcBITS)='1' THEN + OP1in <= bits_out; + ELSIF exec(opcBF)='1' THEN + OP1in <= bf_datareg; + ELSIF exec(opcMOVESR)='1' THEN + OP1in(7 downto 0) <= Flags; + IF exe_datatype="00" THEN + OP1in(15 downto 8) <= "00000000"; + ELSE + OP1in(15 downto 8) <= FlagsSR; + END IF; + ELSIF exec(opcPACK)='1' THEN + OP1in(15 downto 0) <= pack_out; + END IF; + END PROCESS; + +----------------------------------------------------------------------------- +-- addsub +----------------------------------------------------------------------------- +PROCESS (OP1out, OP2out, execOPC, datatype, Flags, long_start, movem_presub, exe_datatype, exec, addsub_a, addsub_b, opaddsub, + notaddsub_b, add_result, c_in, sndOPC) + BEGIN + addsub_a <= OP1out; + IF exec(get_bfoffset)='1' THEN + IF sndOPC(11)='1' THEN + addsub_a <= OP1out(31)&OP1out(31)&OP1out(31)&OP1out(31 downto 3); + ELSE + addsub_a <= "000000000000000000000000000000"&sndOPC(10 downto 9); + END IF; + END IF; + + IF exec(subidx)='1' THEN + opaddsub <= '1'; + ELSE + opaddsub <= '0'; + END IF; + + c_in(0) <='0'; + addsub_b <= OP2out; + IF execOPC='0' AND exec(OP2out_one)='0' AND exec(get_bfoffset)='0'THEN + IF long_start='0' AND datatype="00" AND exec(use_SP)='0' THEN + addsub_b <= "00000000000000000000000000000001"; + ELSIF long_start='0' AND exe_datatype="10" AND (exec(presub) OR exec(postadd) OR movem_presub)='1' THEN + IF exec(movem_action)='1' THEN + addsub_b <= "00000000000000000000000000000110"; + ELSE + addsub_b <= "00000000000000000000000000000100"; + END IF; + ELSE + addsub_b <= "00000000000000000000000000000010"; + END IF; + ELSE + IF (exec(use_XZFlag)='1' AND Flags(4)='1') OR exec(opcCHK)='1' THEN + c_in(0) <= '1'; + END IF; + opaddsub <= exec(addsub); + END IF; + + IF opaddsub='0' OR long_start='1' THEN --ADD + notaddsub_b <= '0'&addsub_b&c_in(0); + ELSE --SUB + notaddsub_b <= NOT ('0'&addsub_b&c_in(0)); + END IF; + add_result <= (('0'&addsub_a¬addsub_b(0))+notaddsub_b); + c_in(1) <= add_result(9) XOR addsub_a(8) XOR addsub_b(8); + c_in(2) <= add_result(17) XOR addsub_a(16) XOR addsub_b(16); + c_in(3) <= add_result(33); + addsub_q <= add_result(32 downto 1); + addsub_ofl(0) <= (c_in(1) XOR add_result(8) XOR addsub_a(7) XOR addsub_b(7)); --V Byte + addsub_ofl(1) <= (c_in(2) XOR add_result(16) XOR addsub_a(15) XOR addsub_b(15)); --V Word + addsub_ofl(2) <= (c_in(3) XOR add_result(32) XOR addsub_a(31) XOR addsub_b(31)); --V Long + c_out <= c_in(3 downto 1); + END PROCESS; + +------------------------------------------------------------------------------ +--ALU +------------------------------------------------------------------------------ +PROCESS (OP1out, OP2out, pack_a, niba_hc, niba_h, niba_l, niba_lc, nibs_hc, nibs_h, nibs_l, nibs_lc, Flags, exe_opcode) + BEGIN + IF exe_opcode(7 downto 6) = "01" THEN + -- PACK + pack_a <= std_logic_vector(unsigned(OP1out(15 downto 0))+unsigned(OP2out(15 downto 0))); + pack_out <= "00000000" & pack_a(11 downto 8) & pack_a(3 downto 0); + ELSE + -- UNPK + pack_a <= "0000" & OP2out(7 downto 4) & "0000" & OP2out(3 downto 0); + pack_out <= std_logic_vector(unsigned(OP1out(15 downto 0))+unsigned(pack_a)); + END IF; + +--BCD_ARITH------------------------------------------------------------------- + --ADC + bcd_a <= niba_hc&(niba_h(4 downto 1)+('0',niba_hc,niba_hc,'0'))&(niba_l(4 downto 1)+('0',niba_lc,niba_lc,'0')); + niba_l <= ('0'&OP1out(3 downto 0)&'1') + ('0'&OP2out(3 downto 0)&Flags(4)); + niba_lc <= niba_l(5) OR (niba_l(4) AND niba_l(3)) OR (niba_l(4) AND niba_l(2)); + + niba_h <= ('0'&OP1out(7 downto 4)&'1') + ('0'&OP2out(7 downto 4)&niba_lc); + niba_hc <= niba_h(5) OR (niba_h(4) AND niba_h(3)) OR (niba_h(4) AND niba_h(2)); + --SBC + bcd_s <= nibs_hc&(nibs_h(4 downto 1)-('0',nibs_hc,nibs_hc,'0'))&(nibs_l(4 downto 1)-('0',nibs_lc,nibs_lc,'0')); + nibs_l <= ('0'&OP1out(3 downto 0)&'0') - ('0'&OP2out(3 downto 0)&Flags(4)); + nibs_lc <= nibs_l(5); + + nibs_h <= ('0'&OP1out(7 downto 4)&'0') - ('0'&OP2out(7 downto 4)&nibs_lc); + nibs_hc <= nibs_h(5); + END PROCESS; + +----------------------------------------------------------------------------- +-- Bits +----------------------------------------------------------------------------- +PROCESS (clk, exe_opcode, OP1out, OP2out, one_bit_in, bchg, bset, bit_Number, sndOPC, reg_QB) + BEGIN + IF rising_edge(clk) THEN + IF clkena_lw = '1' THEN + bchg <= '0'; + bset <= '0'; + CASE opcode(7 downto 6) IS + WHEN "01" => --bchg + bchg <= '1'; + WHEN "11" => --bset + bset <= '1'; + WHEN OTHERS => NULL; + END CASE; + END IF; + END IF; + + IF exe_opcode(8)='0' THEN + IF exe_opcode(5 downto 4)="00" THEN + bit_number <= sndOPC(4 downto 0); + ELSE + bit_number <= "00"&sndOPC(2 downto 0); + END IF; + ELSE + IF exe_opcode(5 downto 4)="00" THEN + bit_number <= reg_QB(4 downto 0); + ELSE + bit_number <= "00"®_QB(2 downto 0); + END IF; + END IF; + + one_bit_in <= OP1out(to_integer(unsigned(bit_Number))); + bits_out <= OP1out; + bits_out(to_integer(unsigned(bit_Number))) <= (bchg AND NOT one_bit_in) OR bset ; + END PROCESS; + +----------------------------------------------------------------------------- +-- Bit Field +----------------------------------------------------------------------------- +PROCESS (clk, mux, mask, bitnr, bf_ins, bf_bchg, bf_bset, bf_exts, bf_shift, inmux0, inmux1, inmux2, inmux3, bf_set2, OP1out, OP2out, result_tmp, bf_ext_in, + shift, datareg, bf_NFlag, result, reg_QB, sign, bf_d32, bf_s32, copy, bf_loffset, copymux0, copymux1, copymux2, copymux3, bf_width) + BEGIN + IF rising_edge(clk) THEN + IF clkena_lw = '1' THEN + bf_bset <= '0'; + bf_bchg <= '0'; + bf_ins <= '0'; + bf_exts <= '0'; + bf_fffo <= '0'; + bf_d32 <= '0'; + bf_s32 <= '0'; + CASE opcode(10 downto 8) IS + WHEN "010" => bf_bchg <= '1'; --BFCHG + WHEN "011" => bf_exts <= '1'; --BFEXTS +-- WHEN "100" => insert <= (OTHERS =>'0'); --BFCLR + WHEN "101" => bf_fffo <= '1'; --BFFFO + WHEN "110" => bf_bset <= '1'; --BFSET + WHEN "111" => bf_ins <= '1'; --BFINS + bf_s32 <= '1'; + WHEN OTHERS => NULL; + END CASE; + IF opcode(4 downto 3)="00" THEN + bf_d32 <= '1'; + END IF; + bf_ext_out <= result(39 downto 32); + END IF; + END IF; + shift <= bf_ext_in&OP2out; + IF bf_s32='1' THEN + shift(39 downto 32) <= OP2out(7 downto 0); + END IF; + + IF bf_shift(0)='1' THEN + inmux0 <= shift(0)&shift(39 downto 1); + ELSE + inmux0 <= shift; + END IF; + IF bf_shift(1)='1' THEN + inmux1 <= inmux0(1 downto 0)&inmux0(39 downto 2); + ELSE + inmux1 <= inmux0; + END IF; + IF bf_shift(2)='1' THEN + inmux2 <= inmux1(3 downto 0)&inmux1(39 downto 4); + ELSE + inmux2 <= inmux1; + END IF; + IF bf_shift(3)='1' THEN + inmux3 <= inmux2(7 downto 0)&inmux2(31 downto 8); + ELSE + inmux3 <= inmux2(31 downto 0); + END IF; + IF bf_shift(4)='1' THEN + bf_set2(31 downto 0) <= inmux3(15 downto 0)&inmux3(31 downto 16); + ELSE + bf_set2(31 downto 0) <= inmux3; + END IF; + + IF bf_loffset(4)='1' THEN + copymux3 <= sign(15 downto 0)&sign(31 downto 16); + ELSE + copymux3 <= sign; + END IF; + IF bf_loffset(3)='1' THEN + copymux2(31 downto 0) <= copymux3(23 downto 0)©mux3(31 downto 24); + ELSE + copymux2(31 downto 0) <= copymux3; + END IF; + IF bf_d32='1' THEN + copymux2(39 downto 32) <= copymux3(7 downto 0); + ELSE + copymux2(39 downto 32) <= "11111111"; + END IF; + IF bf_loffset(2)='1' THEN + copymux1 <= copymux2(35 downto 0)©mux2(39 downto 36); + ELSE + copymux1 <= copymux2; + END IF; + IF bf_loffset(1)='1' THEN + copymux0 <= copymux1(37 downto 0)©mux1(39 downto 38); + ELSE + copymux0 <= copymux1; + END IF; + IF bf_loffset(0)='1' THEN + copy <= copymux0(38 downto 0)©mux0(39); + ELSE + copy <= copymux0; + END IF; + + result_tmp <= bf_ext_in&OP1out; + IF bf_ins='1' THEN + datareg <= reg_QB; + ELSE + datareg <= bf_set2; + END IF; + IF bf_ins='1' THEN + result(31 downto 0) <= bf_set2; + result(39 downto 32) <= bf_set2(7 downto 0); + ELSIF bf_bchg='1' THEN + result(31 downto 0) <= NOT OP1out; + result(39 downto 32) <= NOT bf_ext_in; + ELSE + result <= (OTHERS => '0'); + END IF; + IF bf_bset='1' THEN + result <= (OTHERS => '1'); + END IF; + + sign <= (OTHERS => '0'); + bf_NFlag <= datareg(to_integer(unsigned(bf_width))); + FOR i in 0 to 31 LOOP + IF i>bf_width(4 downto 0) THEN + datareg(i) <= '0'; + sign(i) <= '1'; + END IF; + END LOOP; + + FOR i in 0 to 39 LOOP + IF copy(i)='1' THEN + result(i) <= result_tmp(i); + END IF; + END LOOP; + + IF bf_exts='1' AND bf_NFlag='1' THEN + bf_datareg <= datareg OR sign; + ELSE + bf_datareg <= datareg; + END IF; +-- bf_datareg <= copy(31 downto 0); +-- result(31 downto 0)<=datareg; +--BFFFO + mask <= datareg; + bf_firstbit <= '0'&bitnr; + bitnr <= "11111"; + IF mask(31 downto 28)="0000" THEN + IF mask(27 downto 24)="0000" THEN + IF mask(23 downto 20)="0000" THEN + IF mask(19 downto 16)="0000" THEN + bitnr(4) <= '0'; + IF mask(15 downto 12)="0000" THEN + IF mask(11 downto 8)="0000" THEN + bitnr(3) <= '0'; + IF mask(7 downto 4)="0000" THEN + bitnr(2) <= '0'; + mux <= mask(3 downto 0); + ELSE + mux <= mask(7 downto 4); + END IF; + ELSE + mux <= mask(11 downto 8); + bitnr(2) <= '0'; + END IF; + ELSE + mux <= mask(15 downto 12); + END IF; + ELSE + mux <= mask(19 downto 16); + bitnr(3) <= '0'; + bitnr(2) <= '0'; + END IF; + ELSE + mux <= mask(23 downto 20); + bitnr(3) <= '0'; + END IF; + ELSE + mux <= mask(27 downto 24); + bitnr(2) <= '0'; + END IF; + ELSE + mux <= mask(31 downto 28); + END IF; + + IF mux(3 downto 2)="00" THEN + bitnr(1) <= '0'; + IF mux(1)='0' THEN + bitnr(0) <= '0'; + END IF; + ELSE + IF mux(3)='0' THEN + bitnr(0) <= '0'; + END IF; + END IF; + END PROCESS; + +----------------------------------------------------------------------------- +-- Rotation +----------------------------------------------------------------------------- +PROCESS (exe_opcode, OP1out, Flags, rot_bits, rot_msb, rot_lsb, rot_rot, exec) + BEGIN + CASE exe_opcode(7 downto 6) IS + WHEN "00" => --Byte + rot_rot <= OP1out(7); + WHEN "01"|"11" => --Word + rot_rot <= OP1out(15); + WHEN "10" => --Long + rot_rot <= OP1out(31); + WHEN OTHERS => NULL; + END CASE; + + CASE rot_bits IS + WHEN "00" => --ASL, ASR + rot_lsb <= '0'; + rot_msb <= rot_rot; + WHEN "01" => --LSL, LSR + rot_lsb <= '0'; + rot_msb <= '0'; + WHEN "10" => --ROXL, ROXR + rot_lsb <= Flags(4); + rot_msb <= Flags(4); + WHEN "11" => --ROL, ROR + rot_lsb <= rot_rot; + rot_msb <= OP1out(0); + WHEN OTHERS => NULL; + END CASE; + + IF exec(rot_nop)='1' THEN + rot_out <= OP1out; + rot_X <= Flags(4); + IF rot_bits="10" THEN --ROXL, ROXR + rot_C <= Flags(4); + ELSE + rot_C <= '0'; + END IF; + ELSE + IF exe_opcode(8)='1' THEN --left + rot_out <= OP1out(30 downto 0)&rot_lsb; + rot_X <= rot_rot; + rot_C <= rot_rot; + ELSE --right + rot_X <= OP1out(0); + rot_C <= OP1out(0); + rot_out <= rot_msb&OP1out(31 downto 1); + CASE exe_opcode(7 downto 6) IS + WHEN "00" => --Byte + rot_out(7) <= rot_msb; + WHEN "01"|"11" => --Word + rot_out(15) <= rot_msb; + WHEN OTHERS => NULL; + END CASE; + END IF; + END IF; + END PROCESS; + +------------------------------------------------------------------------------ +--CCR op +------------------------------------------------------------------------------ +PROCESS (clk, Reset, exe_opcode, exe_datatype, Flags, last_data_read, OP2out, flag_z, OP1IN, c_out, addsub_ofl, + bcd_s, bcd_a, exec) + BEGIN + IF exec(andiSR)='1' THEN + CCRin <= Flags AND last_data_read(7 downto 0); + ELSIF exec(eoriSR)='1' THEN + CCRin <= Flags XOR last_data_read(7 downto 0); + ELSIF exec(oriSR)='1' THEN + CCRin <= Flags OR last_data_read(7 downto 0); + ELSE + CCRin <= OP2out(7 downto 0); + END IF; + +------------------------------------------------------------------------------ +--Flags +------------------------------------------------------------------------------ + flag_z <= "000"; + IF exec(use_XZFlag)='1' AND flags(2)='0' THEN + flag_z <= "000"; + ELSIF OP1in(7 downto 0)="00000000" THEN + flag_z(0) <= '1'; + IF OP1in(15 downto 8)="00000000" THEN + flag_z(1) <= '1'; + IF OP1in(31 downto 16)="0000000000000000" THEN + flag_z(2) <= '1'; + END IF; + END IF; + END IF; + +-- --Flags NZVC + IF exe_datatype="00" THEN --Byte + set_flags <= OP1IN(7)&flag_z(0)&addsub_ofl(0)&c_out(0); + IF exec(opcABCD)='1' THEN + set_flags(0) <= bcd_a(8); + ELSIF exec(opcSBCD)='1' THEN + set_flags(0) <= bcd_s(8); + END IF; + ELSIF exe_datatype="10" OR exec(opcCPMAW)='1' THEN --Long + set_flags <= OP1IN(31)&flag_z(2)&addsub_ofl(2)&c_out(2); + ELSE --Word + set_flags <= OP1IN(15)&flag_z(1)&addsub_ofl(1)&c_out(1); + END IF; + + IF rising_edge(clk) THEN + IF clkena_lw = '1' THEN + IF exec(directSR)='1' OR set_stop='1' THEN + Flags(7 downto 0) <= data_read(7 downto 0); + END IF; + IF exec(directCCR)='1' THEN + Flags(7 downto 0) <= data_read(7 downto 0); + END IF; + + IF exec(opcROT)='1' THEN + asl_VFlag <= ((set_flags(3) XOR rot_rot) OR asl_VFlag); + ELSE + asl_VFlag <= '0'; + END IF; + IF exec(to_CCR)='1' THEN + Flags(7 downto 0) <= CCRin(7 downto 0); --CCR + ELSIF Z_error='1' THEN + IF exe_opcode(8)='0' THEN + Flags(3 downto 0) <= reg_QA(31)&"000"; + ELSE + Flags(3 downto 0) <= "0100"; + END IF; + ELSIF exec(no_Flags)='0' THEN + IF exec(opcADD)='1' THEN + Flags(4) <= set_flags(0); + ELSIF exec(opcROT)='1' AND rot_bits/="11" AND exec(rot_nop)='0' THEN + Flags(4) <= rot_X; + END IF; + + IF (exec(opcADD) OR exec(opcCMP))='1' THEN + Flags(3 downto 0) <= set_flags; + ELSIF exec(opcDIVU)='1' AND DIV_Mode/=3 THEN + IF V_Flag='1' THEN + Flags(3 downto 0) <= "1010"; + ELSE + Flags(3 downto 0) <= OP1IN(15)&flag_z(1)&"00"; + END IF; + ELSIF exec(write_reminder)='1' AND MUL_Mode/=3 THEN -- z-flag MULU.l + Flags(3) <= set_flags(3); + Flags(2) <= set_flags(2) AND Flags(2); + Flags(1) <= '0'; + Flags(0) <= '0'; + ELSIF exec(write_lowlong)='1' AND (MUL_Mode=1 OR MUL_Mode=2) THEN -- flag MULU.l + Flags(3) <= set_flags(3); + Flags(2) <= set_flags(2); + Flags(1) <= set_mV_Flag; --V + Flags(0) <= '0'; + ELSIF exec(opcOR)='1' OR exec(opcAND)='1' OR exec(opcEOR)='1' OR exec(opcMOVE)='1' OR exec(opcMOVEQ)='1' OR exec(opcSWAP)='1' OR exec(opcBF)='1' OR (exec(opcMULU)='1' AND MUL_Mode/=3) THEN + Flags(1 downto 0) <= "00"; + Flags(3 downto 2) <= set_flags(3 downto 2); + IF exec(opcBF)='1' THEN + Flags(3) <= bf_NFlag; + END IF; + ELSIF exec(opcROT)='1' THEN + Flags(3 downto 2) <= set_flags(3 downto 2); + Flags(0) <= rot_C; + IF rot_bits="00" AND ((set_flags(3) XOR rot_rot) OR asl_VFlag)='1' THEN --ASL/ASR + Flags(1) <= '1'; + ELSE + Flags(1) <= '0'; + END IF; + ELSIF exec(opcBITS)='1' THEN + Flags(2) <= NOT one_bit_in; + ELSIF exec(opcCHK)='1' THEN + IF exe_datatype="01" THEN --Word + Flags(3) <= OP1out(15); + ELSE + Flags(3) <= OP1out(31); + END IF; + IF OP1out(15 downto 0)=X"0000" AND (exe_datatype="01" OR OP1out(31 downto 16)=X"0000") THEN + Flags(2) <='1'; + ELSE + Flags(2) <='0'; + END IF; + Flags(1 downto 0) <= "00"; + END IF; + END IF; + END IF; + Flags(7 downto 5) <= "000"; + END IF; + END PROCESS; + +------------------------------------------------------------------------------- +---- MULU/MULS +------------------------------------------------------------------------------- +PROCESS (exe_opcode, OP2out, muls_msb, mulu_reg, FAsign, mulu_sign, reg_QA, faktorB, result_mulu, signedOP) + BEGIN + IF (signedOP='1' AND faktorB(31)='1') OR FAsign='1' THEN + muls_msb <= mulu_reg(63); + ELSE + muls_msb <= '0'; + END IF; + + IF signedOP='1' AND faktorB(31)='1' THEN + mulu_sign <= '1'; + ELSE + mulu_sign <= '0'; + END IF; + + IF MUL_Mode=0 THEN -- 16 Bit + result_mulu(63 downto 32) <= muls_msb&mulu_reg(63 downto 33); + result_mulu(15 downto 0) <= 'X'&mulu_reg(15 downto 1); + IF mulu_reg(0)='1' THEN + IF FAsign='1' THEN + result_mulu(63 downto 47) <= (muls_msb&mulu_reg(63 downto 48)-(mulu_sign&faktorB(31 downto 16))); + ELSE + result_mulu(63 downto 47) <= (muls_msb&mulu_reg(63 downto 48)+(mulu_sign&faktorB(31 downto 16))); + END IF; + END IF; + ELSE -- 32 Bit + result_mulu <= muls_msb&mulu_reg(63 downto 1); + IF mulu_reg(0)='1' THEN + IF FAsign='1' THEN + result_mulu(63 downto 31) <= (muls_msb&mulu_reg(63 downto 32)-(mulu_sign&faktorB)); + ELSE + result_mulu(63 downto 31) <= (muls_msb&mulu_reg(63 downto 32)+(mulu_sign&faktorB)); + END IF; + END IF; + END IF; + IF exe_opcode(15)='1' OR MUL_Mode=0 THEN + faktorB(31 downto 16) <= OP2out(15 downto 0); + faktorB(15 downto 0) <= (OTHERS=>'0'); + ELSE + faktorB <= OP2out; + END IF; + IF (result_mulu(63 downto 32)=X"00000000" AND (signedOP='0' OR result_mulu(31)='0')) OR + (result_mulu(63 downto 32)=X"FFFFFFFF" AND signedOP='1' AND result_mulu(31)='1') THEN + set_mV_Flag <= '0'; + ELSE + set_mV_Flag <= '1'; + END IF; + END PROCESS; + +PROCESS (clk) + BEGIN + IF rising_edge(clk) THEN + IF clkena_lw='1' THEN + IF micro_state=mul1 THEN + mulu_reg(63 downto 32) <= (OTHERS=>'0'); + IF divs='1' AND ((exe_opcode(15)='1' AND reg_QA(15)='1') OR (exe_opcode(15)='0' AND reg_QA(31)='1')) THEN --MULS Neg faktor + FAsign <= '1'; + mulu_reg(31 downto 0) <= 0-reg_QA; + ELSE + FAsign <= '0'; + mulu_reg(31 downto 0) <= reg_QA; + END IF; + ELSIF exec(opcMULU)='0' THEN + mulu_reg <= result_mulu; + END IF; + END IF; + END IF; + END PROCESS; + +------------------------------------------------------------------------------- +---- DIVU/DIVS +------------------------------------------------------------------------------- + +PROCESS (execOPC, OP1out, OP2out, div_reg, div_neg, div_bit, div_sub, div_quot, OP1_sign, div_over, result_div, reg_QA, opcode, sndOPC, divs, exe_opcode, reg_QB, + signedOP, nozero, div_qsign, OP2outext) + BEGIN + divs <= (opcode(15) AND opcode(8)) OR (NOT opcode(15) AND sndOPC(11)); + divisor(15 downto 0) <= (OTHERS=> '0'); + divisor(63 downto 32) <= (OTHERS=> divs AND reg_QA(31)); + IF exe_opcode(15)='1' OR DIV_Mode=0 THEN + divisor(47 downto 16) <= reg_QA; + ELSE + divisor(31 downto 0) <= reg_QA; + IF exe_opcode(14)='1' AND sndOPC(10)='1' THEN + divisor(63 downto 32) <= reg_QB; + END IF; + END IF; + IF signedOP='1' OR opcode(15)='0' THEN + OP2outext <= OP2out(31 downto 16); + ELSE + OP2outext <= (OTHERS=> '0'); + END IF; + IF signedOP='1' AND OP2out(31) ='1' THEN + div_sub <= (div_reg(63 downto 31))+('1'&OP2out(31 downto 0)); + ELSE + div_sub <= (div_reg(63 downto 31))-('0'&OP2outext(15 downto 0)&OP2out(15 downto 0)); + END IF; + IF DIV_Mode=0 THEN + div_bit <= div_sub(16); + ELSE + div_bit <= div_sub(32); + END IF; + IF div_bit='1' THEN + div_quot(63 downto 32) <= div_reg(62 downto 31); + ELSE + div_quot(63 downto 32) <= div_sub(31 downto 0); + END IF; + div_quot(31 downto 0) <= div_reg(30 downto 0)&NOT div_bit; + + + IF ((nozero='1' AND signedOP='1' AND (OP2out(31) XOR OP1_sign XOR div_neg XOR div_qsign)='1' ) --Overflow DIVS + OR (signedOP='0' AND div_over(32)='0')) AND DIV_Mode/=3 THEN --Overflow DIVU + set_V_Flag <= '1'; + ELSE + set_V_Flag <= '0'; + END IF; + END PROCESS; + +PROCESS (clk) + BEGIN + IF rising_edge(clk) THEN + IF clkena_lw='1' THEN + V_Flag <= set_V_Flag; + signedOP <= divs; + IF micro_state=div1 THEN + nozero <= '0'; + IF divs='1' AND divisor(63)='1' THEN -- Neg divisor + OP1_sign <= '1'; + div_reg <= 0-divisor; + ELSE + OP1_sign <= '0'; + div_reg <= divisor; + END IF; + ELSE + div_reg <= div_quot; + nozero <= NOT div_bit OR nozero; + END IF; + IF micro_state=div2 THEN + div_qsign <= NOT div_bit; + div_neg <= signedOP AND (OP2out(31) XOR OP1_sign); + IF DIV_Mode=0 THEN + div_over(32 downto 16) <= ('0'&div_reg(47 downto 32))-('0'&OP2out(15 downto 0)); + ELSE + div_over <= ('0'&div_reg(63 downto 32))-('0'&OP2out); + END IF; + END IF; + IF exec(write_reminder)='0' THEN +-- IF exec_DIVU='0' THEN + IF div_neg='1' THEN + result_div(31 downto 0) <= 0-div_quot(31 downto 0); + ELSE + result_div(31 downto 0) <= div_quot(31 downto 0); + END IF; + + IF OP1_sign='1' THEN + result_div(63 downto 32) <= 0-div_quot(63 downto 32); + ELSE + result_div(63 downto 32) <= div_quot(63 downto 32); + END IF; + END IF; + END IF; + END IF; + END PROCESS; +END; diff --git a/TG68K_Pack.vhd b/TG68K_Pack.vhd new file mode 100644 index 0000000..fd3c8f4 --- /dev/null +++ b/TG68K_Pack.vhd @@ -0,0 +1,250 @@ +------------------------------------------------------------------------------ +------------------------------------------------------------------------------ +-- -- +-- Copyright (c) 2009-2013 Tobias Gubener -- +-- Subdesign fAMpIGA by TobiFlex -- +-- -- +-- This source file 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 3 of the License, or -- +-- (at your option) any later version. -- +-- -- +-- This source file 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, see . -- +-- -- +------------------------------------------------------------------------------ +------------------------------------------------------------------------------ +library IEEE; +use IEEE.std_logic_1164.all; + +package TG68K_Pack is + + type micro_states is (idle, nop, ld_nn, st_nn, ld_dAn1, ld_AnXn1, ld_AnXn2, st_dAn1, ld_AnXnbd1, ld_AnXnbd2, ld_AnXnbd3, + ld_229_1, ld_229_2, ld_229_3, ld_229_4, st_229_1, st_229_2, st_229_3, st_229_4, + st_AnXn1, st_AnXn2, bra1, bsr1, bsr2, nopnop, dbcc1, movem1, movem2, movem3, + andi, op_AxAy, cmpm, link1, link2, unlink1, unlink2, int1, int2, int3, int4, rte1, rte2, rte3, trap0, trap1, trap2, trap3, + trap4, trap5, trap6, movec1, movep1, movep2, movep3, movep4, movep5, rota1, bf1, + mul1, mul2, mul_end1, mul_end2, div1, div2, div3, div4, div_end1, div_end2, pack1, pack2, pack3); + + constant opcMOVE : integer := 0; -- + constant opcMOVEQ : integer := 1; -- + constant opcMOVESR : integer := 2; -- + constant opcADD : integer := 3; -- + constant opcADDQ : integer := 4; -- + constant opcOR : integer := 5; -- + constant opcAND : integer := 6; -- + constant opcEOR : integer := 7; -- + constant opcCMP : integer := 8; -- + constant opcROT : integer := 9; -- + constant opcCPMAW : integer := 10; + constant opcEXT : integer := 11; -- + constant opcABCD : integer := 12; -- + constant opcSBCD : integer := 13; -- + constant opcBITS : integer := 14; -- + constant opcSWAP : integer := 15; -- + constant opcScc : integer := 16; -- + constant andiSR : integer := 17; -- + constant eoriSR : integer := 18; -- + constant oriSR : integer := 19; -- + constant opcMULU : integer := 20; -- + constant opcDIVU : integer := 21; -- + constant dispouter : integer := 22; -- + constant rot_nop : integer := 23; -- + constant ld_rot_cnt : integer := 24; -- + constant writePC_add : integer := 25; -- + constant ea_data_OP1 : integer := 26; -- + constant ea_data_OP2 : integer := 27; -- + constant use_XZFlag : integer := 28; -- + constant get_bfoffset : integer := 29; -- + constant save_memaddr : integer := 30; -- + constant opcCHK : integer := 31; -- + constant movec_rd : integer := 32; -- + constant movec_wr : integer := 33; -- + constant Regwrena : integer := 34; -- + constant update_FC : integer := 35; -- + constant linksp : integer := 36; -- + constant movepl : integer := 37; -- + constant update_ld : integer := 38; -- + constant OP1addr : integer := 39; -- + constant write_reg : integer := 40; -- + constant changeMode : integer := 41; -- + constant ea_build : integer := 42; -- + constant trap_chk : integer := 43; -- + constant store_ea_data : integer := 44; -- + constant addrlong : integer := 45; -- + constant postadd : integer := 46; -- + constant presub : integer := 47; -- + constant subidx : integer := 48; -- + constant no_Flags : integer := 49; -- + constant use_SP : integer := 50; -- + constant to_CCR : integer := 51; -- + constant to_SR : integer := 52; -- + constant OP2out_one : integer := 53; -- + constant OP1out_zero : integer := 54; -- + constant mem_addsub : integer := 55; -- + constant addsub : integer := 56; -- + constant directPC : integer := 57; -- + constant direct_delta : integer := 58; -- + constant directSR : integer := 59; -- + constant directCCR : integer := 60; -- + constant exg : integer := 61; -- + constant get_ea_now : integer := 62; -- + constant ea_to_pc : integer := 63; -- + constant hold_dwr : integer := 64; -- + constant to_USP : integer := 65; -- + constant from_USP : integer := 66; -- + constant write_lowlong : integer := 67; -- + constant write_reminder : integer := 68; -- + constant movem_action : integer := 69; -- + constant briefext : integer := 70; -- + constant get_2ndOPC : integer := 71; -- + constant mem_byte : integer := 72; -- + constant longaktion : integer := 73; -- + constant opcRESET : integer := 74; -- + constant opcBF : integer := 75; -- + constant opcBFwb : integer := 76; -- + constant s2nd_hbits : integer := 77; -- + constant opcPACK : integer := 77; -- +-- constant s2nd_hbits : integer := 77; -- + + +-- constant : integer := 75; -- +-- constant : integer := 76; -- +-- constant : integer := 7; -- +-- constant : integer := 7; -- +-- constant : integer := 7; -- + + constant lastOpcBit : integer := 77; + + type rTG68K_opc is record + opcMOVE : bit; + opcMOVEQ : bit; + opcMOVESR : bit; + opcADD : bit; + opcADDQ : bit; + opcOR : bit; + opcAND : bit; + opcEOR : bit; + opcCMP : bit; + opcROT : bit; + opcCPMAW : bit; + opcEXT : bit; + opcABCD : bit; + opcSBCD : bit; + opcBITS : bit; + opcSWAP : bit; + opcScc : bit; + andiSR : bit; + eoriSR : bit; + oriSR : bit; + opcMULU : bit; + opcDIVU : bit; + dispouter : bit; + rot_nop : bit; + ld_rot_cnt : bit; + writePC_add : bit; + ea_data_OP1 : bit; + ea_data_OP2 : bit; + use_XZFlag : bit; + get_bfoffset : bit; + save_memaddr : bit; + opcCHK : bit; + movec_rd : bit; + movec_wr : bit; + Regwrena : bit; + update_FC : bit; + linksp : bit; + movepl : bit; + update_ld : bit; + OP1addr : bit; + write_reg : bit; + changeMode : bit; + ea_build : bit; + trap_chk : bit; + store_ea_data : bit; + addrlong : bit; + postadd : bit; + presub : bit; + subidx : bit; + no_Flags : bit; + use_SP : bit; + to_CCR : bit; + to_SR : bit; + OP2out_one : bit; + OP1out_zero : bit; + mem_addsub : bit; + addsub : bit; + directPC : bit; + direct_delta : bit; + directSR : bit; + directCCR : bit; + exg : bit; + get_ea_now : bit; + ea_to_pc : bit; + hold_dwr : bit; + to_USP : bit; + from_USP : bit; + write_lowlong : bit; + write_reminder : bit; + movem_action : bit; + briefext : bit; + get_2ndOPC : bit; + mem_byte : bit; + longaktion : bit; + opcRESET : bit; + opcBF : bit; + opcBFwb : bit; + s2nd_hbits : bit; + end record; + + component TG68K_ALU + generic( + MUL_Mode : integer := 0; --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no MUL, + DIV_Mode : integer := 0 --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no DIV, + ); + port( + clk : in std_logic; + Reset : in std_logic; + clkena_lw : in std_logic:='1'; + execOPC : in bit; + exe_condition : in std_logic; + exec_tas : in std_logic; + long_start : in bit; + movem_presub : in bit; + set_stop : in bit; + Z_error : in bit; + rot_bits : in std_logic_vector(1 downto 0); + exec : in bit_vector(lastOpcBit downto 0); + OP1out : in std_logic_vector(31 downto 0); + OP2out : in std_logic_vector(31 downto 0); + reg_QA : in std_logic_vector(31 downto 0); + reg_QB : in std_logic_vector(31 downto 0); + opcode : in std_logic_vector(15 downto 0); + datatype : in std_logic_vector(1 downto 0); + exe_opcode : in std_logic_vector(15 downto 0); + exe_datatype : in std_logic_vector(1 downto 0); + sndOPC : in std_logic_vector(15 downto 0); + last_data_read : in std_logic_vector(15 downto 0); + data_read : in std_logic_vector(15 downto 0); + FlagsSR : in std_logic_vector(7 downto 0); + micro_state : in micro_states; + bf_ext_in : in std_logic_vector(7 downto 0); + bf_ext_out : out std_logic_vector(7 downto 0); + bf_shift : in std_logic_vector(5 downto 0); + bf_width : in std_logic_vector(5 downto 0); + bf_loffset : in std_logic_vector(4 downto 0); + + set_V_Flag : buffer bit; + Flags : buffer std_logic_vector(7 downto 0); + c_out : buffer std_logic_vector(2 downto 0); + addsub_q : buffer std_logic_vector(31 downto 0); + ALUout : out std_logic_vector(31 downto 0) + ); + end component; + +end; diff --git a/TG68KdotC_Kernel.vhd b/TG68KdotC_Kernel.vhd new file mode 100644 index 0000000..b6c48e1 --- /dev/null +++ b/TG68KdotC_Kernel.vhd @@ -0,0 +1,3318 @@ +------------------------------------------------------------------------------ +------------------------------------------------------------------------------ +-- -- +-- Copyright (c) 2009-2013 Tobias Gubener -- +-- Patches by MikeJ, Till Harbaum, Rok Krajnk, ... -- +-- Subdesign fAMpIGA by TobiFlex -- +-- -- +-- This source file 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 3 of the License, or -- +-- (at your option) any later version. -- +-- -- +-- This source file 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, see . -- +-- -- +------------------------------------------------------------------------------ +------------------------------------------------------------------------------ + +-- optimize Register file + +-- to do 68010: +-- (MOVEC) +-- BKPT +-- RTD +-- MOVES +-- +-- to do 68020: +-- (CALLM) +-- (RETM) + +-- CAS, CAS2 +-- CHK2 +-- CMP2 +-- cpXXX Coprozessor stuff +-- TRAPcc + +-- done 020: +-- PACK, UNPK +-- Bitfields +-- address modes +-- long bra +-- DIVS.L, DIVU.L +-- LINK long +-- MULS.L, MULU.L +-- extb.l + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; +use work.TG68K_Pack.all; + +entity TG68KdotC_Kernel is + generic( + SR_Read : integer := 0; --0=>user, 1=>privileged, 2=>switchable with CPU(0) + VBR_Stackframe : integer := 0; --0=>no, 1=>yes/extended, 2=>switchable with CPU(0) + extAddr_Mode : integer := 0; --0=>no, 1=>yes, 2=>switchable with CPU(1) + MUL_Mode : integer := 0; --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no MUL, + DIV_Mode : integer := 0; --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no DIV, + BitField : integer := 0 --0=>no, 1=>yes, 2=>switchable with CPU(1) + ); + port(clk : in std_logic; + nReset : in std_logic; --low active + clkena_in : in std_logic:='1'; + data_in : in std_logic_vector(15 downto 0); + IPL : in std_logic_vector(2 downto 0):="111"; + IPL_autovector : in std_logic:='0'; + berr : in std_logic:='0'; -- only 68000 Stackpointer dummy + CPU : in std_logic_vector(1 downto 0):="00"; -- 00->68000 01->68010 11->68020(only some parts - yet) + addr : buffer std_logic_vector(31 downto 0); + data_write : out std_logic_vector(15 downto 0); + nWr : out std_logic; + nUDS : out std_logic; + nLDS : out std_logic; + busstate : out std_logic_vector(1 downto 0); -- 00-> fetch code 10->read data 11->write data 01->no memaccess + nResetOut : out std_logic; + FC : out std_logic_vector(2 downto 0); + clr_berr : out std_logic; +-- for debug + skipFetch : out std_logic; + regin : buffer std_logic_vector(31 downto 0); + CACR_out : buffer std_logic_vector(3 downto 0); + VBR_out : buffer std_logic_vector(31 downto 0) + ); +end TG68KdotC_Kernel; + +--nBS : std_logic_vector(3 downto 0); -- nBS0 is 31..24 3 is 7..0, active LOW +--SIZ : std_logic_vector(1 downto 0); +--ACK for 16/32 bit transfer? +architecture logic of TG68KdotC_Kernel is + + + signal syncReset : std_logic_vector(3 downto 0); + signal Reset : std_logic; + signal clkena_lw : std_logic; + signal TG68_PC : std_logic_vector(31 downto 0); + signal tmp_TG68_PC : std_logic_vector(31 downto 0); + signal TG68_PC_add : std_logic_vector(31 downto 0); + signal PC_dataa : std_logic_vector(31 downto 0); + signal PC_datab : std_logic_vector(31 downto 0); + signal memaddr : std_logic_vector(31 downto 0); + signal state : std_logic_vector(1 downto 0); + signal datatype : std_logic_vector(1 downto 0); + signal set_datatype : std_logic_vector(1 downto 0); + signal exe_datatype : std_logic_vector(1 downto 0); + signal setstate : std_logic_vector(1 downto 0); + + signal opcode : std_logic_vector(15 downto 0); + signal exe_opcode : std_logic_vector(15 downto 0); + signal sndOPC : std_logic_vector(15 downto 0); + + signal last_opc_read : std_logic_vector(15 downto 0); + signal registerin : std_logic_vector(31 downto 0); + signal reg_QA : std_logic_vector(31 downto 0); + signal reg_QB : std_logic_vector(31 downto 0); + signal Wwrena,Lwrena : bit; + signal Bwrena : bit; + signal Regwrena_now : bit; + signal rf_dest_addr : std_logic_vector(3 downto 0); + signal rf_source_addr : std_logic_vector(3 downto 0); + signal rf_source_addrd : std_logic_vector(3 downto 0); + + type regfile_t is array(0 to 15) of std_logic_vector(31 downto 0); + signal regfile : regfile_t := (others => (others =>'0')); -- mikej stops sim X issues; + signal RDindex_A : integer range 0 to 15; + signal RDindex_B : integer range 0 to 15; + signal WR_AReg : std_logic; + + + signal memaddr_reg : std_logic_vector(31 downto 0); + signal memaddr_delta : std_logic_vector(31 downto 0); + signal use_base : bit; + + signal ea_data : std_logic_vector(31 downto 0); + signal OP1out : std_logic_vector(31 downto 0); + signal OP2out : std_logic_vector(31 downto 0); + signal OP1outbrief : std_logic_vector(15 downto 0); + signal OP1in : std_logic_vector(31 downto 0); + signal ALUout : std_logic_vector(31 downto 0); + signal data_write_i : std_logic_vector(15 downto 0); + signal data_write_tmp : std_logic_vector(31 downto 0); + signal data_write_muxin : std_logic_vector(31 downto 0); + signal data_write_mux : std_logic_vector(47 downto 0); + signal nextpass : bit; + signal setnextpass : bit; + signal setdispbyte : bit; + signal setdisp : bit; + signal regdirectsource : bit; -- checken !!! + signal addsub_q : std_logic_vector(31 downto 0); + signal briefdata : std_logic_vector(31 downto 0); +-- signal c_in : std_logic_vector(3 downto 0); + signal c_out : std_logic_vector(2 downto 0); + + signal mem_address : std_logic_vector(31 downto 0); + signal memaddr_a : std_logic_vector(31 downto 0); + + signal TG68_PC_brw : bit; + signal TG68_PC_word : bit; + signal getbrief : bit; + signal brief : std_logic_vector(15 downto 0); + signal dest_areg : std_logic; + signal source_areg : std_logic; + signal data_is_source : bit; + signal store_in_tmp : bit; + signal write_back : bit; + signal exec_write_back : bit; + signal setstackaddr : bit; + signal writePC : bit; + signal writePCbig : bit; + signal set_writePCbig : bit; + signal setopcode : bit; + signal decodeOPC : bit; + signal execOPC : bit; + signal setexecOPC : bit; + signal endOPC : bit; + signal setendOPC : bit; + signal Flags : std_logic_vector(7 downto 0); -- ...XNZVC + signal FlagsSR : std_logic_vector(7 downto 0); -- T.S..III + signal SRin : std_logic_vector(7 downto 0); + signal exec_DIRECT : bit; + signal exec_tas : std_logic; + signal set_exec_tas : std_logic; + + signal exe_condition : std_logic; + signal ea_only : bit; + signal source_lowbits : bit; + signal source_2ndHbits : bit; + signal source_2ndLbits : bit; + signal dest_2ndHbits : bit; + signal dest_hbits : bit; + signal rot_bits : std_logic_vector(1 downto 0); + signal set_rot_bits : std_logic_vector(1 downto 0); + signal rot_cnt : std_logic_vector(5 downto 0); + signal set_rot_cnt : std_logic_vector(5 downto 0); + signal movem_actiond : bit; + signal movem_regaddr : std_logic_vector(3 downto 0); + signal movem_mux : std_logic_vector(3 downto 0); + signal movem_presub : bit; + signal movem_run : bit; + signal ea_calc_b : std_logic_vector(31 downto 0); + signal set_direct_data : bit; + signal use_direct_data : bit; + signal direct_data : bit; + + signal set_V_Flag : bit; + signal set_vectoraddr : bit; + signal writeSR : bit; + signal trap_berr : bit; + signal trap_illegal : bit; + signal trap_addr_error : bit; + signal trap_priv : bit; + signal trap_trace : bit; + signal trap_1010 : bit; + signal trap_1111 : bit; + signal trap_trap : bit; + signal trap_trapv : bit; + signal trap_interrupt : bit; + signal trapmake : bit; + signal trapd : bit; + signal trap_SR : std_logic_vector(7 downto 0); + signal make_trace : std_logic; + signal make_berr : std_logic; + + signal set_stop : bit; + signal stop : bit; + signal trap_vector : std_logic_vector(31 downto 0); + signal trap_vector_vbr : std_logic_vector(31 downto 0); + signal USP : std_logic_vector(31 downto 0); + + signal IPL_nr : std_logic_vector(2 downto 0); + signal rIPL_nr : std_logic_vector(2 downto 0); + signal IPL_vec : std_logic_vector(7 downto 0); + signal interrupt : bit; + signal setinterrupt : bit; + signal SVmode : std_logic; + signal preSVmode : std_logic; + signal Suppress_Base : bit; + signal set_Suppress_Base : bit; + signal set_Z_error : bit; + signal Z_error : bit; + signal ea_build_now : bit; + signal build_logical : bit; + signal build_bcd : bit; + + signal data_read : std_logic_vector(31 downto 0); + signal bf_ext_in : std_logic_vector(7 downto 0); + signal bf_ext_out : std_logic_vector(7 downto 0); + signal long_start : bit; + signal long_start_alu : bit; + signal long_done : bit; + signal memmask : std_logic_vector(5 downto 0); + signal set_memmask : std_logic_vector(5 downto 0); + signal memread : std_logic_vector(3 downto 0); + signal wbmemmask : std_logic_vector(5 downto 0); + signal memmaskmux : std_logic_vector(5 downto 0); + signal oddout : std_logic; + signal set_oddout : std_logic; + signal PCbase : std_logic; + signal set_PCbase : std_logic; + + signal last_data_read : std_logic_vector(31 downto 0); + signal last_data_in : std_logic_vector(31 downto 0); + + signal bf_offset : std_logic_vector(5 downto 0); + signal bf_width : std_logic_vector(5 downto 0); + signal bf_bhits : std_logic_vector(5 downto 0); + signal bf_shift : std_logic_vector(5 downto 0); + signal alu_width : std_logic_vector(5 downto 0); + signal alu_bf_shift : std_logic_vector(5 downto 0); + signal bf_loffset : std_logic_vector(5 downto 0); + signal alu_bf_loffset : std_logic_vector(5 downto 0); + + signal movec_data : std_logic_vector(31 downto 0); + signal VBR : std_logic_vector(31 downto 0); + signal CACR : std_logic_vector(3 downto 0); + signal DFC : std_logic_vector(2 downto 0); + signal SFC : std_logic_vector(2 downto 0); + + + signal set : bit_vector(lastOpcBit downto 0); + signal set_exec : bit_vector(lastOpcBit downto 0); + signal exec : bit_vector(lastOpcBit downto 0); + + signal micro_state : micro_states; + signal next_micro_state : micro_states; + + attribute syn_ramstyle : string; + attribute syn_ramstyle of regfile : signal is "logic"; + + +BEGIN +ALU: TG68K_ALU + generic map( + MUL_Mode => MUL_Mode, --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no MUL, + DIV_Mode => DIV_Mode --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no DIV, + ) + port map( + clk => clk, --: in std_logic; + Reset => Reset, --: in std_logic; + clkena_lw => clkena_lw, --: in std_logic:='1'; + execOPC => execOPC, --: in bit; + exe_condition => exe_condition, --: in std_logic; + exec_tas => exec_tas, --: in std_logic; + long_start => long_start_alu, --: in bit; + movem_presub => movem_presub, --: in bit; + set_stop => set_stop, --: in bit; + Z_error => Z_error, --: in bit; + rot_bits => rot_bits, --: in std_logic_vector(1 downto 0); + exec => exec, --: in bit_vector(lastOpcBit downto 0); + OP1out => OP1out, --: in std_logic_vector(31 downto 0); + OP2out => OP2out, --: in std_logic_vector(31 downto 0); + reg_QA => reg_QA, --: in std_logic_vector(31 downto 0); + reg_QB => reg_QB, --: in std_logic_vector(31 downto 0); + opcode => opcode, --: in std_logic_vector(15 downto 0); + datatype => datatype, --: in std_logic_vector(1 downto 0); + exe_opcode => exe_opcode, --: in std_logic_vector(15 downto 0); + exe_datatype => exe_datatype, --: in std_logic_vector(1 downto 0); + sndOPC => sndOPC, --: in std_logic_vector(15 downto 0); + last_data_read => last_data_read(15 downto 0), --: in std_logic_vector(31 downto 0); + data_read => data_read(15 downto 0), --: in std_logic_vector(31 downto 0); + FlagsSR => FlagsSR, --: in std_logic_vector(7 downto 0); + micro_state => micro_state, --: in micro_states; + bf_ext_in => bf_ext_in, + bf_ext_out => bf_ext_out, + bf_shift => alu_bf_shift, + bf_width => alu_width, + bf_loffset => alu_bf_loffset(4 downto 0), + set_V_Flag => set_V_Flag, --: buffer bit; + Flags => Flags, --: buffer std_logic_vector(8 downto 0); + c_out => c_out, --: buffer std_logic_vector(2 downto 0); + addsub_q => addsub_q, --: buffer std_logic_vector(31 downto 0); + ALUout => ALUout --: buffer std_logic_vector(31 downto 0) + ); + + long_start_alu <= to_bit(NOT memmaskmux(3)); +----------------------------------------------------------------------------- +-- Bus control +----------------------------------------------------------------------------- + nWr <= '0' WHEN state="11" ELSE '1'; + busstate <= state; + nResetOut <= '0' WHEN exec(opcRESET)='1' ELSE '1'; + + -- does shift for byte access. Note active low me + -- should produce address error on 68000 + memmaskmux <= memmask WHEN addr(0)='1' ELSE memmask(4 downto 0)&'1'; + + nUDS <= memmaskmux(5); + nLDS <= memmaskmux(4); + + -- drive output data, output bytes on both half-words during byte write + data_write( 7 downto 0) <= data_write_i( 7 downto 0) WHEN memmaskmux(4)='0' ELSE data_write_i(15 downto 8); + data_write(15 downto 8) <= data_write_i(15 downto 8) WHEN memmaskmux(5)='0' ELSE data_write_i( 7 downto 0); + + clkena_lw <= '1' WHEN clkena_in='1' AND memmaskmux(3)='1' ELSE '0'; -- step + clr_berr <= '1' WHEN setopcode='1' AND trap_berr='1' ELSE '0'; + + PROCESS (clk, nReset) + BEGIN + IF nReset='0' THEN + syncReset <= "0000"; + Reset <= '1'; + ELSIF rising_edge(clk) THEN + IF clkena_in='1' THEN + syncReset <= syncReset(2 downto 0)&'1'; + Reset <= NOT syncReset(3); + END IF; + END IF; + END PROCESS; + +PROCESS (clk, long_done, last_data_in, data_in, addr, long_start, memmaskmux, memread, memmask, data_read) + BEGIN + IF memmaskmux(4)='0' THEN + data_read <= last_data_in(15 downto 0)&data_in; + ELSE + data_read <= last_data_in(23 downto 0)&data_in(15 downto 8); + END IF; + IF memread(0)='1' OR (memread(1 downto 0)="10" AND memmaskmux(4)='1')THEN + data_read(31 downto 16) <= (OTHERS=>data_read(15)); + END IF; + + IF rising_edge(clk) THEN + IF clkena_lw='1' AND state="10" THEN + IF memmaskmux(4)='0' THEN + bf_ext_in <= last_data_in(23 downto 16); + ELSE + bf_ext_in <= last_data_in(31 downto 24); + END IF; + END IF; + IF Reset='1' THEN + last_data_read <= (OTHERS => '0'); + ELSIF clkena_in='1' THEN + IF state="00" OR exec(update_ld)='1' THEN + last_data_read <= data_read; + IF state(1)='0' AND memmask(1)='0' THEN + last_data_read(31 downto 16) <= last_opc_read; + ELSIF state(1)='0' OR memread(1)='1' THEN + last_data_read(31 downto 16) <= (OTHERS=>data_in(15)); + END IF; + END IF; + last_data_in <= last_data_in(15 downto 0)&data_in(15 downto 0); + + END IF; + END IF; + long_start <= to_bit(NOT memmask(1)); + long_done <= to_bit(NOT memread(1)); + END PROCESS; + +PROCESS (long_start, reg_QB, data_write_tmp, exec, data_read, data_write_mux, memmaskmux, bf_ext_out, + data_write_muxin, memmask, oddout, addr) + BEGIN + IF exec(write_reg)='1' THEN + data_write_muxin <= reg_QB; + ELSE + data_write_muxin <= data_write_tmp; + END IF; + + IF BitField=0 THEN + IF oddout=addr(0) THEN + data_write_mux <= "XXXXXXXX"&"XXXXXXXX"&data_write_muxin; + ELSE + data_write_mux <= "XXXXXXXX"&data_write_muxin&"XXXXXXXX"; + END IF; + ELSE + IF oddout=addr(0) THEN + data_write_mux <= "XXXXXXXX"&bf_ext_out&data_write_muxin; + ELSE + data_write_mux <= bf_ext_out&data_write_muxin&"XXXXXXXX"; + END IF; + END IF; + + IF memmaskmux(1)='0' THEN + data_write_i <= data_write_mux(47 downto 32); + ELSIF memmaskmux(3)='0' THEN + data_write_i <= data_write_mux(31 downto 16); + ELSE + data_write_i <= data_write_mux(15 downto 0); + END IF; + IF exec(mem_byte)='1' THEN --movep + data_write_i(7 downto 0) <= data_write_tmp(15 downto 8); + END IF; + END PROCESS; + +----------------------------------------------------------------------------- +-- Registerfile +----------------------------------------------------------------------------- +PROCESS (clk, regfile, RDindex_A, RDindex_B, exec) + BEGIN + reg_QA <= regfile(RDindex_A); + reg_QB <= regfile(RDindex_B); + IF rising_edge(clk) THEN + IF clkena_lw='1' THEN + rf_source_addrd <= rf_source_addr; + WR_AReg <= rf_dest_addr(3); + RDindex_A <= conv_integer(rf_dest_addr(3 downto 0)); + RDindex_B <= conv_integer(rf_source_addr(3 downto 0)); + IF Wwrena='1' THEN + regfile(RDindex_A) <= regin; + END IF; + + IF exec(to_USP)='1' THEN + USP <= reg_QA; + END IF; + END IF; + END IF; + END PROCESS; + +----------------------------------------------------------------------------- +-- Write Reg +----------------------------------------------------------------------------- +PROCESS (OP1in, reg_QA, Regwrena_now, Bwrena, Lwrena, exe_datatype, WR_AReg, movem_actiond, exec, ALUout, memaddr, memaddr_a, ea_only, USP, movec_data) + BEGIN + regin <= ALUout; + IF exec(save_memaddr)='1' THEN + regin <= memaddr; + ELSIF exec(get_ea_now)='1' AND ea_only='1' THEN + regin <= memaddr_a; + ELSIF exec(from_USP)='1' THEN + regin <= USP; + ELSIF exec(movec_rd)='1' THEN + regin <= movec_data; + END IF; + + IF Bwrena='1' THEN + regin(15 downto 8) <= reg_QA(15 downto 8); + END IF; + IF Lwrena='0' THEN + regin(31 downto 16) <= reg_QA(31 downto 16); + END IF; + + Bwrena <= '0'; + Wwrena <= '0'; + Lwrena <= '0'; + IF exec(presub)='1' OR exec(postadd)='1' OR exec(changeMode)='1' THEN -- -(An)+ + Wwrena <= '1'; + Lwrena <= '1'; + ELSIF Regwrena_now='1' THEN --dbcc + Wwrena <= '1'; + ELSIF exec(Regwrena)='1' THEN --read (mem) + Wwrena <= '1'; + CASE exe_datatype IS + WHEN "00" => --BYTE + Bwrena <= '1'; + WHEN "01" => --WORD + IF WR_AReg='1' OR movem_actiond='1' THEN + Lwrena <='1'; + END IF; + WHEN OTHERS => --LONG + Lwrena <= '1'; + END CASE; + END IF; + END PROCESS; + +----------------------------------------------------------------------------- +-- set dest regaddr +----------------------------------------------------------------------------- +PROCESS (opcode, rf_source_addrd, brief, setstackaddr, dest_hbits, dest_areg, data_is_source, sndOPC, exec, set, dest_2ndHbits) + BEGIN + IF exec(movem_action) ='1' THEN + rf_dest_addr <= rf_source_addrd; + ELSIF set(briefext)='1' THEN + rf_dest_addr <= brief(15 downto 12); + ELSIF set(get_bfoffset)='1' THEN + rf_dest_addr <= sndOPC(9 downto 6); + ELSIF dest_2ndHbits='1' THEN + rf_dest_addr <= sndOPC(15 downto 12); + ELSIF set(write_reminder)='1' THEN + rf_dest_addr <= sndOPC(3 downto 0); + ELSIF setstackaddr='1' THEN + rf_dest_addr <= "1111"; + ELSIF dest_hbits='1' THEN + rf_dest_addr <= dest_areg&opcode(11 downto 9); + ELSE + IF opcode(5 downto 3)="000" OR data_is_source='1' THEN + rf_dest_addr <= dest_areg&opcode(2 downto 0); + ELSE + rf_dest_addr <= '1'&opcode(2 downto 0); + END IF; + END IF; + END PROCESS; + +----------------------------------------------------------------------------- +-- set source regaddr +----------------------------------------------------------------------------- +PROCESS (opcode, movem_presub, movem_regaddr, source_lowbits, source_areg, sndOPC, exec, set, source_2ndLbits, source_2ndHbits) + BEGIN + IF exec(movem_action)='1' OR set(movem_action) ='1' THEN + IF movem_presub='1' THEN + rf_source_addr <= movem_regaddr XOR "1111"; + ELSE + rf_source_addr <= movem_regaddr; + END IF; + ELSIF source_2ndLbits='1' THEN + rf_source_addr <= sndOPC(3 downto 0); + ELSIF source_2ndHbits='1' THEN + rf_source_addr <= sndOPC(15 downto 12); + ELSIF source_lowbits='1' THEN + rf_source_addr <= source_areg&opcode(2 downto 0); + ELSIF exec(linksp)='1' THEN + rf_source_addr <= "1111"; + ELSE + rf_source_addr <= source_areg&opcode(11 downto 9); + END IF; + END PROCESS; + +----------------------------------------------------------------------------- +-- set OP1out +----------------------------------------------------------------------------- +PROCESS (reg_QA, store_in_tmp, ea_data, long_start, addr, exec, memmaskmux, data_write_tmp) + BEGIN + OP1out <= reg_QA; + IF exec(OP1out_zero)='1' THEN + OP1out <= (OTHERS => '0'); + ELSIF exec(ea_data_OP1)='1' AND store_in_tmp='1' THEN + OP1out <= ea_data; + ELSIF exec(opcPACK)='1' THEN + OP1out <= data_write_tmp; + ELSIF exec(movem_action)='1' OR memmaskmux(3)='0' OR exec(OP1addr)='1' THEN + OP1out <= addr; + END IF; + END PROCESS; + +----------------------------------------------------------------------------- +-- set OP2out +----------------------------------------------------------------------------- +PROCESS (OP2out, reg_QB, exe_opcode, exe_datatype, execOPC, exec, use_direct_data, + store_in_tmp, data_write_tmp, ea_data) + BEGIN + OP2out(15 downto 0) <= reg_QB(15 downto 0); + OP2out(31 downto 16) <= (OTHERS => OP2out(15)); + IF exec(OP2out_one)='1' THEN + OP2out(15 downto 0) <= "1111111111111111"; + ELSIF exec(opcEXT)='1' THEN + IF exe_opcode(6)='0' OR exe_opcode(8)='1' THEN --ext.w + OP2out(15 downto 8) <= (OTHERS => OP2out(7)); + END IF; + ELSIF (use_direct_data='1' AND exec(opcPACK)='0') OR (exec(exg)='1' AND execOPC='1') OR exec(get_bfoffset)='1' THEN + OP2out <= data_write_tmp; + ELSIF (exec(ea_data_OP1)='0' AND store_in_tmp='1') OR exec(ea_data_OP2)='1' THEN + OP2out <= ea_data; + ELSIF exec(opcMOVEQ)='1' THEN + OP2out(7 downto 0) <= exe_opcode(7 downto 0); + OP2out(15 downto 8) <= (OTHERS => exe_opcode(7)); + ELSIF exec(opcADDQ)='1' THEN + OP2out(2 downto 0) <= exe_opcode(11 downto 9); + IF exe_opcode(11 downto 9)="000" THEN + OP2out(3) <='1'; + ELSE + OP2out(3) <='0'; + END IF; + OP2out(15 downto 4) <= (OTHERS => '0'); + ELSIF exe_datatype="10" THEN + OP2out(31 downto 16) <= reg_QB(31 downto 16); + END IF; + END PROCESS; + + +----------------------------------------------------------------------------- +-- handle EA_data, data_write +----------------------------------------------------------------------------- +PROCESS (clk) + BEGIN + IF rising_edge(clk) THEN + IF Reset = '1' THEN + store_in_tmp <='0'; + exec_write_back <= '0'; + direct_data <= '0'; + use_direct_data <= '0'; + Z_error <= '0'; + ELSIF clkena_lw='1' THEN + direct_data <= '0'; + IF state="11" THEN + exec_write_back <= '0'; + ELSIF setstate="10" AND write_back='1' THEN + exec_write_back <= '1'; + END IF; + + + IF set_direct_data='1' THEN + direct_data <= '1'; + IF set_exec(opcPACK)='1' THEN + use_direct_data <= '0'; + ELSE + use_direct_data <= '1'; + END IF; + ELSIF endOPC='1' THEN + use_direct_data <= '0'; + END IF; + exec_DIRECT <= set_exec(opcMOVE); + + IF endOPC='1' THEN + store_in_tmp <='0'; + Z_error <= '0'; + ELSE + IF set_Z_error='1' THEN + Z_error <= '1'; + END IF; + IF set_exec(opcMOVE)='1' AND state="11" THEN + use_direct_data <= '1'; + END IF; + + IF state="10" THEN + store_in_tmp <= '1'; + END IF; + IF direct_data='1' AND state="00" THEN + store_in_tmp <= '1'; + END IF; + END IF; + IF state="10" THEN + ea_data <= data_read; + ELSIF exec(get_2ndOPC)='1' OR set_PCbase='1' THEN --TH cmpi (d16,PC) fix + ea_data <= addr; + ELSIF exec(store_ea_data)='1' OR (direct_data='1' AND state="00") THEN + ea_data <= last_data_read; + END IF; + + IF writePC='1' THEN + data_write_tmp <= TG68_PC; + ELSIF exec(writePC_add)='1' THEN + data_write_tmp <= TG68_PC_add; + ELSIF micro_state=trap0 THEN + data_write_tmp(15 downto 0) <= trap_vector(15 downto 0); + ELSIF exec(hold_dwr)='1' THEN + data_write_tmp <= data_write_tmp; + ELSIF exec(exg)='1' THEN + data_write_tmp <= OP1out; + ELSIF exec(get_ea_now)='1' AND ea_only='1' THEN -- ist for pea + data_write_tmp <= addr; + ELSIF execOPC='1' or micro_state=pack2 THEN + data_write_tmp <= ALUout; + ELSIF (exec_DIRECT='1' AND state="10") THEN + data_write_tmp <= data_read; + IF exec(movepl)='1' THEN + data_write_tmp(31 downto 8) <= data_write_tmp(23 downto 0); + END IF; + ELSIF exec(movepl)='1' THEN + data_write_tmp(15 downto 0) <= reg_QB(31 downto 16); + ELSIF direct_data='1' THEN + data_write_tmp <= last_data_read; + ELSIF writeSR='1'THEN + data_write_tmp(15 downto 0) <= trap_SR(7 downto 0)& Flags(7 downto 0); + ELSE + data_write_tmp <= OP2out; + END IF; + END IF; + END IF; + END PROCESS; + +----------------------------------------------------------------------------- +-- brief +----------------------------------------------------------------------------- +PROCESS (brief, OP1out, OP1outbrief, cpu) + BEGIN + IF brief(11)='1' THEN + OP1outbrief <= OP1out(31 downto 16); + ELSE + OP1outbrief <= (OTHERS=>OP1out(15)); + END IF; + briefdata <= OP1outbrief&OP1out(15 downto 0); + IF extAddr_Mode=1 OR (cpu(1)='1' AND extAddr_Mode=2) THEN + CASE brief(10 downto 9) IS -- mikej SCALE factor + WHEN "00" => briefdata <= OP1outbrief&OP1out(15 downto 0); + WHEN "01" => briefdata <= OP1outbrief(14 downto 0)&OP1out(15 downto 0)&'0'; + WHEN "10" => briefdata <= OP1outbrief(13 downto 0)&OP1out(15 downto 0)&"00"; + WHEN "11" => briefdata <= OP1outbrief(12 downto 0)&OP1out(15 downto 0)&"000"; + WHEN OTHERS => NULL; + END CASE; + END IF; + END PROCESS; + +----------------------------------------------------------------------------- +-- MEM_IO +----------------------------------------------------------------------------- +PROCESS (clk, setdisp, memaddr_a, briefdata, memaddr_delta, setdispbyte, datatype, interrupt, rIPL_nr, IPL_vec, + memaddr_reg, reg_QA, use_base, VBR, last_data_read, trap_vector, exec, set, cpu) + BEGIN + + IF rising_edge(clk) THEN + IF clkena_lw='1' THEN + trap_vector(31 downto 8) <= (others => '0'); + IF trap_berr='1' THEN + trap_vector(7 downto 0) <= X"08"; + END IF; + IF trap_addr_error='1' THEN + trap_vector(7 downto 0) <= X"0C"; + END IF; + IF trap_illegal='1' THEN + trap_vector(7 downto 0) <= X"10"; + END IF; + IF z_error='1' THEN + trap_vector(7 downto 0) <= X"14"; + END IF; + IF exec(trap_chk)='1' THEN + trap_vector(7 downto 0) <= X"18"; + END IF; + IF trap_trapv='1' THEN + trap_vector(7 downto 0) <= X"1C"; + END IF; + IF trap_priv='1' THEN + trap_vector(7 downto 0) <= X"20"; + END IF; + IF trap_trace='1' THEN + trap_vector(7 downto 0) <= X"24"; + END IF; + IF trap_1010='1' THEN + trap_vector(7 downto 0) <= X"28"; + END IF; + IF trap_1111='1' THEN + trap_vector(7 downto 0) <= X"2C"; + END IF; + IF trap_trap='1' THEN + trap_vector(7 downto 0) <= "10"&opcode(3 downto 0)&"00"; + END IF; + IF trap_interrupt='1' THEN + trap_vector(9 downto 0) <= IPL_vec & "00"; --TH + END IF; + -- TH TODO: non-autovector IRQs + END IF; + END IF; + IF VBR_Stackframe=0 OR (cpu(0)='0' AND VBR_Stackframe=2) THEN + trap_vector_vbr <= trap_vector; + ELSE + trap_vector_vbr <= trap_vector+VBR; + END IF; + + memaddr_a(4 downto 0) <= "00000"; + memaddr_a(7 downto 5) <= (OTHERS=>memaddr_a(4)); + memaddr_a(15 downto 8) <= (OTHERS=>memaddr_a(7)); + memaddr_a(31 downto 16) <= (OTHERS=>memaddr_a(15)); + IF setdisp='1' THEN + IF exec(briefext)='1' THEN + memaddr_a <= briefdata+memaddr_delta; + ELSIF setdispbyte='1' THEN + memaddr_a(7 downto 0) <= last_data_read(7 downto 0); + ELSE + memaddr_a <= last_data_read; + END IF; + ELSIF set(presub)='1' THEN + IF set(longaktion)='1' THEN + memaddr_a(4 downto 0) <= "11100"; + ELSIF datatype="00" AND set(use_SP)='0' THEN + memaddr_a(4 downto 0) <= "11111"; + ELSE + memaddr_a(4 downto 0) <= "11110"; + END IF; + ELSIF interrupt='1' THEN + memaddr_a(4 downto 0) <= '1'&rIPL_nr&'0'; + END IF; + + IF rising_edge(clk) THEN + IF clkena_in='1' THEN + IF exec(get_2ndOPC)='1' OR (state="10" AND memread(0)='1') THEN + tmp_TG68_PC <= addr; + END IF; + use_base <= '0'; + + IF memmaskmux(3)='0' THEN + memaddr_delta <= addsub_q; + ELSIF exec(mem_addsub)='1' THEN + -- note, this should give an exception for 68000 + if exec(movem_action) = '1' and memmaskmux(3) = '1' and (memmaskmux(5 downto 4) = "10" or memmaskmux(5 downto 4) = "01") and (movem_presub = '0') then + memaddr_delta <= addr; -- hold for non-aligned case, only when incrementing + else + memaddr_delta <= addsub_q; + end if; + ELSIF state="01" AND exec_write_back='1' THEN + memaddr_delta <= tmp_TG68_PC; + ELSIF exec(direct_delta)='1' THEN + memaddr_delta <= data_read; + ELSIF exec(ea_to_pc)='1' AND setstate="00" THEN + memaddr_delta <= addr; + ELSIF set(addrlong)='1' THEN + memaddr_delta <= last_data_read; + ELSIF setstate="00" THEN + memaddr_delta <= TG68_PC_add; + ELSIF exec(dispouter)='1' THEN + memaddr_delta <= ea_data+memaddr_a; + ELSIF set_vectoraddr='1' THEN + memaddr_delta <= trap_vector_vbr; + ELSE + memaddr_delta <= memaddr_a; + IF interrupt='0' AND Suppress_Base='0' THEN +-- IF interrupt='0' AND Suppress_Base='0' AND setstate(1)='1' THEN + use_base <= '1'; + END IF; + END IF; + + IF (long_done='0' AND state(1)='1') OR movem_presub='0' THEN + memaddr <= addr; + END IF; + END IF; + END IF; + -- if access done, and not aligned, don't increment + addr <= memaddr_reg+memaddr_delta; + IF use_base='0' THEN + memaddr_reg <= (others=>'0'); + ELSE + memaddr_reg <= reg_QA; + END IF; + END PROCESS; + +----------------------------------------------------------------------------- +-- PC Calc + fetch opcode +----------------------------------------------------------------------------- +PROCESS (clk, IPL, setstate, state, exec_write_back, set_direct_data, next_micro_state, stop, make_trace, make_berr, IPL_nr, FlagsSR, set_rot_cnt, opcode, writePCbig, set_exec, exec, + PC_dataa, PC_datab, setnextpass, last_data_read, TG68_PC_brw, TG68_PC_word, Z_error, trap_trap, trap_trapv, interrupt, tmp_TG68_PC, TG68_PC) + BEGIN + + PC_dataa <= TG68_PC; + IF TG68_PC_brw = '1' THEN + PC_dataa <= tmp_TG68_PC; + END IF; + + PC_datab(2 downto 0) <= (others => '0'); + PC_datab(3) <= PC_datab(2); + PC_datab(7 downto 4) <= (others => PC_datab(3)); + PC_datab(15 downto 8) <= (others => PC_datab(7)); + PC_datab(31 downto 16) <= (others => PC_datab(15)); + IF interrupt='1' THEN + PC_datab(2 downto 1) <= "11"; + END IF; + IF exec(writePC_add) ='1' THEN + IF writePCbig='1' THEN + PC_datab(3) <= '1'; + PC_datab(1) <= '1'; + ELSE + PC_datab(2) <= '1'; + END IF; + IF trap_trap='1' OR trap_trapv='1' OR exec(trap_chk)='1' OR Z_error='1' THEN + PC_datab(1) <= '1'; + END IF; + ELSIF state="00" THEN + PC_datab(1) <= '1'; + END IF; + IF TG68_PC_brw = '1' THEN + IF TG68_PC_word='1' THEN + PC_datab <= last_data_read; + ELSE + PC_datab(7 downto 0) <= opcode(7 downto 0); + END IF; + END IF; + + TG68_PC_add <= PC_dataa+PC_datab; + + setopcode <= '0'; + setendOPC <= '0'; + setinterrupt <= '0'; + IF setstate="00" AND next_micro_state=idle AND setnextpass='0' AND (exec_write_back='0' OR state="11") AND set_rot_cnt="000001" AND set_exec(opcCHK)='0'THEN + setendOPC <= '1'; + IF FlagsSR(2 downto 0) + set_memmask <= "101111"; + WHEN "001" => + set_memmask <= "100111"; + WHEN "010" => + set_memmask <= "100011"; + WHEN "011" => + set_memmask <= "100001"; + WHEN OTHERS => + set_memmask <= "100000"; + END CASE; + IF setstate="00" THEN + set_memmask <= "100111"; + END IF; + END PROCESS; + +------------------------------------------------------------------------------ +--SR op +------------------------------------------------------------------------------ +PROCESS (clk, Reset, FlagsSR, last_data_read, OP2out, exec) + BEGIN + IF exec(andiSR)='1' THEN + SRin <= FlagsSR AND last_data_read(15 downto 8); + ELSIF exec(eoriSR)='1' THEN + SRin <= FlagsSR XOR last_data_read(15 downto 8); + ELSIF exec(oriSR)='1' THEN + SRin <= FlagsSR OR last_data_read(15 downto 8); + ELSE + SRin <= OP2out(15 downto 8); + END IF; + + IF rising_edge(clk) THEN + IF Reset='1' THEN + FlagsSR(5) <= '1'; + FC(2) <= '1'; + SVmode <= '1'; + preSVmode <= '1'; + FlagsSR(2 downto 0) <= "111"; + make_trace <= '0'; + ELSIF clkena_lw = '1' THEN + IF setopcode='1' THEN + make_trace <= FlagsSR(7); + IF set(changeMode)='1' THEN + SVmode <= NOT SVmode; + ELSE + SVmode <= preSVmode; + END IF; + END IF; + IF set(changeMode)='1' THEN + preSVmode <= NOT preSVmode; + FlagsSR(5) <= NOT preSVmode; + FC(2) <= NOT preSVmode; + END IF; + IF micro_state=trap3 THEN + FlagsSR(7) <= '0'; + END IF; + IF trap_trace='1' AND state="10" THEN + make_trace <= '0'; + END IF; + IF exec(directSR)='1' OR set_stop='1' THEN + FlagsSR <= data_read(15 downto 8); + END IF; + IF interrupt='1' AND trap_interrupt='1' THEN + FlagsSR(2 downto 0) <=rIPL_nr; + END IF; +-- IF exec(to_CCR)='1' AND exec(to_SR)='1' THEN + IF exec(to_SR)='1' THEN + FlagsSR(7 downto 0) <= SRin; --SR + FC(2) <= SRin(5); +-- END IF; + ELSIF exec(update_FC)='1' THEN + FC(2) <= FlagsSR(5); + END IF; + IF interrupt='1' THEN + FC(2) <= '1'; + END IF; + END IF; + END IF; + END PROCESS; + +----------------------------------------------------------------------------- +-- decode opcode +----------------------------------------------------------------------------- +PROCESS (clk, cpu, OP1out, OP2out, opcode, exe_condition, nextpass, micro_state, decodeOPC, state, setexecOPC, Flags, FlagsSR, direct_data, build_logical, + build_bcd, set_Z_error, trapd, movem_run, last_data_read, set, set_V_Flag, z_error, trap_trace, trap_interrupt, + SVmode, preSVmode, stop, long_done, ea_only, setstate, execOPC, exec_write_back, exe_datatype, + datatype, interrupt, c_out, trapmake, rot_cnt, brief, addr, + long_start, set_datatype, sndOPC, set_exec, exec, ea_build_now, reg_QA, reg_QB, make_berr, trap_berr) + BEGIN + TG68_PC_brw <= '0'; + setstate <= "00"; + Regwrena_now <= '0'; + movem_presub <= '0'; + setnextpass <= '0'; + regdirectsource <= '0'; + setdisp <= '0'; + setdispbyte <= '0'; + getbrief <= '0'; + dest_areg <= '0'; + source_areg <= '0'; + data_is_source <= '0'; + write_back <= '0'; + setstackaddr <= '0'; + writePC <= '0'; + ea_build_now <= '0'; + set_rot_bits <= "XX"; + set_rot_cnt <= "000001"; + dest_hbits <= '0'; + source_lowbits <= '0'; + source_2ndHbits <= '0'; + source_2ndLbits <= '0'; + dest_2ndHbits <= '0'; + ea_only <= '0'; + set_direct_data <= '0'; + set_exec_tas <= '0'; + trap_illegal <='0'; + trap_addr_error <= '0'; + trap_priv <='0'; + trap_1010 <='0'; + trap_1111 <='0'; + trap_trap <='0'; + trap_trapv <= '0'; + trapmake <='0'; + set_vectoraddr <='0'; + writeSR <= '0'; + set_stop <= '0'; + set_Z_error <= '0'; + + next_micro_state <= idle; + build_logical <= '0'; + build_bcd <= '0'; + skipFetch <= make_berr; + set_writePCbig <= '0'; +-- set_recall_last <= '0'; + set_Suppress_Base <= '0'; + set_PCbase <= '0'; + + IF rot_cnt/="000001" THEN + set_rot_cnt <= rot_cnt-1; + END IF; + set_datatype <= datatype; + + set <= (OTHERS=>'0'); + set_exec <= (OTHERS=>'0'); + set(update_ld) <= '0'; +-- odd_start <= '0'; +------------------------------------------------------------------------------ +--Sourcepass +------------------------------------------------------------------------------ + CASE opcode(7 downto 6) IS + WHEN "00" => datatype <= "00"; --Byte + WHEN "01" => datatype <= "01"; --Word + WHEN OTHERS => datatype <= "10"; --Long + END CASE; + + IF trapmake='1' AND trapd='0' THEN + next_micro_state <= trap0; + IF VBR_Stackframe=0 OR (cpu(0)='0' AND VBR_Stackframe=2) THEN + set(writePC_add) <= '1'; +-- set_datatype <= "10"; + END IF; + IF preSVmode='0' THEN + set(changeMode) <= '1'; + END IF; + setstate <= "01"; + END IF; + IF interrupt='1' AND trap_berr='1' THEN + next_micro_state <= trap0; + IF preSVmode='0' THEN + set(changeMode) <= '1'; + END IF; + setstate <= "01"; + END IF; + IF micro_state=int1 OR (interrupt='1' AND trap_trace='1') THEN + next_micro_state <= trap0; +-- IF cpu(0)='0' THEN +-- set_datatype <= "10"; +-- END IF; + IF preSVmode='0' THEN + set(changeMode) <= '1'; + END IF; + setstate <= "01"; + END IF; + + IF setexecOPC='1' AND FlagsSR(5)/=preSVmode THEN + set(changeMode) <= '1'; +-- setstate <= "01"; +-- next_micro_state <= nop; + END IF; + + IF interrupt='1' AND trap_interrupt='1'THEN +-- skipFetch <= '1'; + next_micro_state <= int1; + set(update_ld) <= '1'; + setstate <= "10"; + END IF; + + IF set(changeMode)='1' THEN + set(to_USP) <= '1'; + set(from_USP) <= '1'; + setstackaddr <='1'; + END IF; + + IF ea_only='0' AND set(get_ea_now)='1' THEN + setstate <= "10"; +-- set_recall_last <= '1'; +-- set(update_ld) <= '0'; + END IF; + + IF setstate(1)='1' AND set_datatype(1)='1' THEN + set(longaktion) <= '1'; + END IF; + + IF (ea_build_now='1' AND decodeOPC='1') OR exec(ea_build)='1' THEN + CASE opcode(5 downto 3) IS --source + WHEN "010"|"011"|"100" => -- -(An)+ + set(get_ea_now) <='1'; + setnextpass <= '1'; + IF opcode(3)='1' THEN --(An)+ + set(postadd) <= '1'; + IF opcode(2 downto 0)="111" THEN + set(use_SP) <= '1'; + END IF; + END IF; + IF opcode(5)='1' THEN -- -(An) + set(presub) <= '1'; + IF opcode(2 downto 0)="111" THEN + set(use_SP) <= '1'; + END IF; + END IF; + WHEN "101" => --(d16,An) + next_micro_state <= ld_dAn1; + WHEN "110" => --(d8,An,Xn) + next_micro_state <= ld_AnXn1; + getbrief <='1'; + WHEN "111" => + CASE opcode(2 downto 0) IS + WHEN "000" => --(xxxx).w + next_micro_state <= ld_nn; + WHEN "001" => --(xxxx).l + set(longaktion) <= '1'; + next_micro_state <= ld_nn; + WHEN "010" => --(d16,PC) + next_micro_state <= ld_dAn1; + set(dispouter) <= '1'; + set_Suppress_Base <= '1'; + set_PCbase <= '1'; + WHEN "011" => --(d8,PC,Xn) + next_micro_state <= ld_AnXn1; + getbrief <= '1'; + set(dispouter) <= '1'; + set_Suppress_Base <= '1'; + set_PCbase <= '1'; + WHEN "100" => --#data + setnextpass <= '1'; + set_direct_data <= '1'; + IF datatype="10" THEN + set(longaktion) <= '1'; + END IF; + WHEN OTHERS => NULL; + END CASE; + WHEN OTHERS => NULL; + END CASE; + END IF; +------------------------------------------------------------------------------ +--prepere opcode +------------------------------------------------------------------------------ + CASE opcode(15 downto 12) IS +-- 0000 ---------------------------------------------------------------------------- + WHEN "0000" => + IF opcode(8)='1' AND opcode(5 downto 3)="001" THEN --movep + datatype <= "00"; --Byte + set(use_SP) <= '1'; --addr+2 + set(no_Flags) <='1'; + IF opcode(7)='0' THEN --to register + set_exec(Regwrena) <= '1'; + set_exec(opcMOVE) <= '1'; + set(movepl) <= '1'; + END IF; + IF decodeOPC='1' THEN + IF opcode(6)='1' THEN + set(movepl) <= '1'; + END IF; + IF opcode(7)='0' THEN + set_direct_data <= '1'; -- to register + END IF; + next_micro_state <= movep1; + END IF; + IF setexecOPC='1' THEN + dest_hbits <='1'; + END IF; + ELSE + IF opcode(8)='1' OR opcode(11 downto 9)="100" THEN --Bits + set_exec(opcBITS) <= '1'; + set_exec(ea_data_OP1) <= '1'; + IF opcode(7 downto 6)/="00" THEN + IF opcode(5 downto 4)="00" THEN + set_exec(Regwrena) <= '1'; + END IF; + write_back <= '1'; + END IF; + IF opcode(5 downto 4)="00" THEN + datatype <= "10"; --Long + ELSE + datatype <= "00"; --Byte + END IF; + IF opcode(8)='0' THEN + IF decodeOPC='1' THEN + next_micro_state <= nop; + set(get_2ndOPC) <= '1'; + set(ea_build) <= '1'; + END IF; + ELSE + ea_build_now <= '1'; + END IF; + ELSIF opcode(11 downto 9)="111" THEN --MOVES not in 68000 + trap_illegal <= '1'; +-- trap_addr_error <= '1'; + trapmake <= '1'; + ELSE --andi, ...xxxi + IF opcode(11 downto 9)="000" THEN --ORI + set_exec(opcOR) <= '1'; + END IF; + IF opcode(11 downto 9)="001" THEN --ANDI + set_exec(opcAND) <= '1'; + END IF; + IF opcode(11 downto 9)="010" OR opcode(11 downto 9)="011" THEN --SUBI, ADDI + set_exec(opcADD) <= '1'; + END IF; + IF opcode(11 downto 9)="101" THEN --EORI + set_exec(opcEOR) <= '1'; + END IF; + IF opcode(11 downto 9)="110" THEN --CMPI + set_exec(opcCMP) <= '1'; + END IF; + IF opcode(7)='0' AND opcode(5 downto 0)="111100" AND (set_exec(opcAND) OR set_exec(opcOR) OR set_exec(opcEOR))='1' THEN --SR + IF decodeOPC='1' AND SVmode='0' AND opcode(6)='1' THEN --SR + trap_priv <= '1'; + trapmake <= '1'; + ELSE + set(no_Flags) <= '1'; + IF decodeOPC='1' THEN + IF opcode(6)='1' THEN + set(to_SR) <= '1'; + END IF; + set(to_CCR) <= '1'; + set(andiSR) <= set_exec(opcAND); + set(eoriSR) <= set_exec(opcEOR); + set(oriSR) <= set_exec(opcOR); + setstate <= "01"; + next_micro_state <= nopnop; + END IF; + END IF; + ELSE + IF decodeOPC='1' THEN + next_micro_state <= andi; + set(ea_build) <= '1'; + set_direct_data <= '1'; + IF datatype="10" THEN + set(longaktion) <= '1'; + END IF; + END IF; + IF opcode(5 downto 4)/="00" THEN + set_exec(ea_data_OP1) <= '1'; + END IF; + IF opcode(11 downto 9)/="110" THEN --CMPI + IF opcode(5 downto 4)="00" THEN + set_exec(Regwrena) <= '1'; + END IF; + write_back <= '1'; + END IF; + IF opcode(10 downto 9)="10" THEN --CMPI, SUBI + set(addsub) <= '1'; + END IF; + END IF; + END IF; + END IF; + +-- 0001, 0010, 0011 ----------------------------------------------------------------- + WHEN "0001"|"0010"|"0011" => --move.b, move.l, move.w + set_exec(opcMOVE) <= '1'; + ea_build_now <= '1'; + IF opcode(8 downto 6)="001" THEN + set(no_Flags) <= '1'; + END IF; + IF opcode(5 downto 4)="00" THEN --Dn, An + IF opcode(8 downto 7)="00" THEN + set_exec(Regwrena) <= '1'; + END IF; + END IF; + CASE opcode(13 downto 12) IS + WHEN "01" => datatype <= "00"; --Byte + WHEN "10" => datatype <= "10"; --Long + WHEN OTHERS => datatype <= "01"; --Word + END CASE; + source_lowbits <= '1'; -- Dn=> An=> + IF opcode(3)='1' THEN + source_areg <= '1'; + END IF; + + IF nextpass='1' OR opcode(5 downto 4)="00" THEN + dest_hbits <= '1'; + IF opcode(8 downto 6)/="000" THEN + dest_areg <= '1'; + END IF; + END IF; +-- IF setstate="10" THEN +-- set(update_ld) <= '0'; +-- END IF; +-- + IF micro_state=idle AND (nextpass='1' OR (opcode(5 downto 4)="00" AND decodeOPC='1')) THEN + CASE opcode(8 downto 6) IS --destination + WHEN "000"|"001" => --Dn,An + set_exec(Regwrena) <= '1'; + WHEN "010"|"011"|"100" => --destination -(an)+ + IF opcode(6)='1' THEN --(An)+ + set(postadd) <= '1'; + IF opcode(11 downto 9)="111" THEN + set(use_SP) <= '1'; + END IF; + END IF; + IF opcode(8)='1' THEN -- -(An) + set(presub) <= '1'; + IF opcode(11 downto 9)="111" THEN + set(use_SP) <= '1'; + END IF; + END IF; + setstate <= "11"; + next_micro_state <= nop; + IF nextpass='0' THEN + set(write_reg) <= '1'; + END IF; + WHEN "101" => --(d16,An) + next_micro_state <= st_dAn1; +-- getbrief <= '1'; + WHEN "110" => --(d8,An,Xn) + next_micro_state <= st_AnXn1; + getbrief <= '1'; + WHEN "111" => + CASE opcode(11 downto 9) IS + WHEN "000" => --(xxxx).w + next_micro_state <= st_nn; + WHEN "001" => --(xxxx).l + set(longaktion) <= '1'; + next_micro_state <= st_nn; + WHEN OTHERS => NULL; + END CASE; + WHEN OTHERS => NULL; + END CASE; + END IF; +---- 0100 ---------------------------------------------------------------------------- + WHEN "0100" => --rts_group + IF opcode(8)='1' THEN --lea + IF opcode(6)='1' THEN --lea + IF opcode(7)='1' THEN + source_lowbits <= '1'; +-- IF opcode(5 downto 3)="000" AND opcode(10)='0' THEN --ext + IF opcode(5 downto 4)="00" THEN --extb.l + set_exec(opcEXT) <= '1'; + set_exec(opcMOVE) <= '1'; + set_exec(Regwrena) <= '1'; +-- IF opcode(6)='0' THEN +-- datatype <= "01"; --WORD +-- END IF; + ELSE + source_areg <= '1'; + ea_only <= '1'; + set_exec(Regwrena) <= '1'; + set_exec(opcMOVE) <='1'; + set(no_Flags) <='1'; + IF opcode(5 downto 3)="010" THEN --lea (Am),An + dest_areg <= '1'; + dest_hbits <= '1'; + ELSE + ea_build_now <= '1'; + END IF; + IF set(get_ea_now)='1' THEN + setstate <= "01"; + set_direct_data <= '1'; + END IF; + IF setexecOPC='1' THEN + dest_areg <= '1'; + dest_hbits <= '1'; + END IF; + END IF; + ELSE + trap_illegal <= '1'; + trapmake <= '1'; + END IF; + ELSE --chk + IF opcode(7)='1' THEN + datatype <= "01"; --Word + set(trap_chk) <= '1'; + IF (c_out(1)='0' OR OP1out(15)='1' OR OP2out(15)='1') AND exec(opcCHK)='1' THEN + trapmake <= '1'; + END IF; + ELSIF cpu(1)='1' THEN --chk long for 68020 + datatype <= "10"; --Long + set(trap_chk) <= '1'; + IF (c_out(2)='1' OR OP1out(31)='1' OR OP2out(31)='1') AND exec(opcCHK)='1' THEN + trapmake <= '1'; + END IF; + ELSE + trap_illegal <= '1'; -- chk long for 68020 + trapmake <= '1'; + END IF; + IF opcode(7)='1' OR cpu(1)='1' THEN + IF (nextpass='1' OR opcode(5 downto 4)="00") AND exec(opcCHK)='0' AND micro_state=idle THEN + set_exec(opcCHK) <= '1'; + END IF; + ea_build_now <= '1'; + set(addsub) <= '1'; + IF setexecOPC='1' THEN + dest_hbits <= '1'; + source_lowbits <='1'; + END IF; + END IF; + END IF; + ELSE + CASE opcode(11 downto 9) IS + WHEN "000"=> + IF opcode(7 downto 6)="11" THEN --move from SR + IF SR_Read=0 OR (cpu(0)='0' AND SR_Read=2) OR SVmode='1' THEN +-- IF SVmode='1' THEN + ea_build_now <= '1'; + set_exec(opcMOVESR) <= '1'; + datatype <= "01"; + write_back <='1'; -- im 68000 wird auch erst gelesen + IF cpu(0)='1' AND state="10" THEN + skipFetch <= '1'; + END IF; + IF opcode(5 downto 4)="00" THEN + set_exec(Regwrena) <= '1'; + END IF; + ELSE + trap_priv <= '1'; + trapmake <= '1'; + END IF; + ELSE --negx + ea_build_now <= '1'; + set_exec(use_XZFlag) <= '1'; + write_back <='1'; + set_exec(opcADD) <= '1'; + set(addsub) <= '1'; + source_lowbits <= '1'; + IF opcode(5 downto 4)="00" THEN + set_exec(Regwrena) <= '1'; + END IF; + IF setexecOPC='1' THEN + set(OP1out_zero) <= '1'; + END IF; + END IF; + WHEN "001"=> + IF opcode(7 downto 6)="11" THEN --move from CCR 68010 + IF SR_Read=1 OR (cpu(0)='1' AND SR_Read=2) THEN + ea_build_now <= '1'; + set_exec(opcMOVESR) <= '1'; + datatype <= "00"; + write_back <='1'; -- im 68000 wird auch erst gelesen + IF opcode(5 downto 4)="00" THEN + set_exec(Regwrena) <= '1'; + END IF; + ELSE + trap_illegal <= '1'; + trapmake <= '1'; + END IF; + ELSE --clr + ea_build_now <= '1'; + write_back <='1'; + set_exec(opcAND) <= '1'; + IF cpu(0)='1' AND state="10" THEN + skipFetch <= '1'; + END IF; + IF setexecOPC='1' THEN + set(OP1out_zero) <= '1'; + END IF; + IF opcode(5 downto 4)="00" THEN + set_exec(Regwrena) <= '1'; + END IF; + END IF; + WHEN "010"=> + ea_build_now <= '1'; + IF opcode(7 downto 6)="11" THEN --move to CCR + datatype <= "01"; + source_lowbits <= '1'; + IF (decodeOPC='1' AND opcode(5 downto 4)="00") OR state="10" OR direct_data='1' THEN + set(to_CCR) <= '1'; + END IF; + ELSE --neg + write_back <='1'; + set_exec(opcADD) <= '1'; + set(addsub) <= '1'; + source_lowbits <= '1'; + IF opcode(5 downto 4)="00" THEN + set_exec(Regwrena) <= '1'; + END IF; + IF setexecOPC='1' THEN + set(OP1out_zero) <= '1'; + END IF; + END IF; + WHEN "011"=> --not, move toSR + IF opcode(7 downto 6)="11" THEN --move to SR + IF SVmode='1' THEN + ea_build_now <= '1'; + datatype <= "01"; + source_lowbits <= '1'; + IF (decodeOPC='1' AND opcode(5 downto 4)="00") OR state="10" OR direct_data='1' THEN + set(to_SR) <= '1'; + set(to_CCR) <= '1'; + END IF; + IF exec(to_SR)='1' OR (decodeOPC='1' AND opcode(5 downto 4)="00") OR state="10" OR direct_data='1' THEN + setstate <="01"; + END IF; + ELSE + trap_priv <= '1'; + trapmake <= '1'; + END IF; + ELSE --not + ea_build_now <= '1'; + write_back <='1'; + set_exec(opcEOR) <= '1'; + set_exec(ea_data_OP1) <= '1'; + IF opcode(5 downto 3)="000" THEN + set_exec(Regwrena) <= '1'; + END IF; + IF setexecOPC='1' THEN + set(OP2out_one) <= '1'; + END IF; + END IF; + WHEN "100"|"110"=> + IF opcode(7)='1' THEN --movem, ext + IF opcode(5 downto 3)="000" AND opcode(10)='0' THEN --ext + source_lowbits <= '1'; + set_exec(opcEXT) <= '1'; + set_exec(opcMOVE) <= '1'; + set_exec(Regwrena) <= '1'; + IF opcode(6)='0' THEN + datatype <= "01"; --WORD + END IF; + ELSE --movem +-- IF opcode(11 downto 7)="10001" OR opcode(11 downto 7)="11001" THEN --MOVEM + ea_only <= '1'; + set(no_Flags) <= '1'; + IF opcode(6)='0' THEN + datatype <= "01"; --Word transfer + END IF; + IF (opcode(5 downto 3)="100" OR opcode(5 downto 3)="011") AND state="01" THEN -- -(An), (An)+ + set_exec(save_memaddr) <= '1'; + set_exec(Regwrena) <= '1'; + END IF; + IF opcode(5 downto 3)="100" THEN -- -(An) + movem_presub <= '1'; + set(subidx) <= '1'; + END IF; + IF state="10" THEN + set(Regwrena) <= '1'; + set(opcMOVE) <= '1'; + END IF; + IF decodeOPC='1' THEN + set(get_2ndOPC) <='1'; + IF opcode(5 downto 3)="010" OR opcode(5 downto 3)="011" OR opcode(5 downto 3)="100" THEN + next_micro_state <= movem1; + ELSE + next_micro_state <= nop; + set(ea_build) <= '1'; + END IF; + END IF; + IF set(get_ea_now)='1' THEN + IF movem_run='1' THEN + set(movem_action) <= '1'; + IF opcode(10)='0' THEN + setstate <="11"; + set(write_reg) <= '1'; + ELSE + setstate <="10"; + END IF; + next_micro_state <= movem2; + set(mem_addsub) <= '1'; + ELSE + setstate <="01"; + END IF; + END IF; + END IF; + ELSE + IF opcode(10)='1' THEN --MUL.L, DIV.L 68020 +-- IF cpu(1)='1' THEN + IF (opcode(6)='1' AND (DIV_Mode=1 OR (cpu(1)='1' AND DIV_Mode=2))) OR + (opcode(6)='0' AND (MUL_Mode=1 OR (cpu(1)='1' AND MUL_Mode=2))) THEN + IF decodeOPC='1' THEN + next_micro_state <= nop; + set(get_2ndOPC) <= '1'; + set(ea_build) <= '1'; + END IF; + IF (micro_state=idle AND nextpass='1') OR (opcode(5 downto 4)="00" AND exec(ea_build)='1')THEN + setstate <="01"; + dest_2ndHbits <= '1'; + source_2ndLbits <= '1'; + IF opcode(6)='1' THEN + next_micro_state <= div1; + ELSE + next_micro_state <= mul1; + set(ld_rot_cnt) <= '1'; + END IF; + END IF; + IF z_error='0' AND set_V_Flag='0' AND set(opcDIVU)='1' THEN + set(Regwrena) <= '1'; + END IF; + source_lowbits <='1'; + IF nextpass='1' OR (opcode(5 downto 4)="00" AND decodeOPC='1') THEN + dest_hbits <= '1'; + END IF; + datatype <= "10"; + ELSE + trap_illegal <= '1'; + trapmake <= '1'; + END IF; + + ELSE --pea, swap + IF opcode(6)='1' THEN + datatype <= "10"; + IF opcode(5 downto 3)="000" THEN --swap + set_exec(opcSWAP) <= '1'; + set_exec(Regwrena) <= '1'; + ELSIF opcode(5 downto 3)="001" THEN --bkpt + + ELSE --pea + ea_only <= '1'; + ea_build_now <= '1'; + IF nextpass='1' AND micro_state=idle THEN + set(presub) <= '1'; + setstackaddr <='1'; + setstate <="11"; + next_micro_state <= nop; + END IF; + IF set(get_ea_now)='1' THEN + setstate <="01"; + END IF; + END IF; + ELSE + IF opcode(5 downto 3)="001" THEN --link.l + datatype <= "10"; + set_exec(opcADD) <= '1'; --for displacement + set_exec(Regwrena) <= '1'; + set(no_Flags) <= '1'; + IF decodeOPC='1' THEN + set(linksp) <= '1'; + set(longaktion) <= '1'; + next_micro_state <= link1; + set(presub) <= '1'; + setstackaddr <='1'; + set(mem_addsub) <= '1'; + source_lowbits <= '1'; + source_areg <= '1'; + set(store_ea_data) <= '1'; + END IF; + ELSE --nbcd + ea_build_now <= '1'; + set_exec(use_XZFlag) <= '1'; + write_back <='1'; + set_exec(opcADD) <= '1'; + set_exec(opcSBCD) <= '1'; + source_lowbits <= '1'; + IF opcode(5 downto 4)="00" THEN + set_exec(Regwrena) <= '1'; + END IF; + IF setexecOPC='1' THEN + set(OP1out_zero) <= '1'; + END IF; + END IF; + END IF; + END IF; + END IF; +-- + WHEN "101"=> --tst, tas 4aFC - illegal + IF opcode(7 downto 2)="111111" THEN --illegal + trap_illegal <= '1'; + trapmake <= '1'; + ELSE + ea_build_now <= '1'; + IF setexecOPC='1' THEN + source_lowbits <= '1'; + IF opcode(3)='1' THEN --MC68020... + source_areg <= '1'; + END IF; + END IF; + set_exec(opcMOVE) <= '1'; + IF opcode(7 downto 6)="11" THEN --tas + set_exec_tas <= '1'; + write_back <= '1'; + datatype <= "00"; --Byte + IF opcode(5 downto 4)="00" THEN + set_exec(Regwrena) <= '1'; + END IF; + END IF; + END IF; +---- WHEN "110"=> + WHEN "111"=> --4EXX +-- +-- ea_only <= '1'; +-- ea_build_now <= '1'; +-- IF nextpass='1' AND micro_state=idle THEN +-- set(presub) <= '1'; +-- setstackaddr <='1'; +-- set(mem_addsub) <= '1'; +-- setstate <="11"; +-- next_micro_state <= nop; +-- END IF; +-- IF set(get_ea_now)='1' THEN +-- setstate <="01"; +-- END IF; +-- + + + + IF opcode(7)='1' THEN --jsr, jmp + datatype <= "10"; + ea_only <= '1'; + ea_build_now <= '1'; + IF exec(ea_to_pc)='1' THEN + next_micro_state <= nop; + END IF; + IF nextpass='1' AND micro_state=idle AND opcode(6)='0' THEN + set(presub) <= '1'; + setstackaddr <='1'; + setstate <="11"; + next_micro_state <= nopnop; + END IF; +-- achtung buggefahr + IF micro_state=ld_AnXn1 AND brief(8)='0'THEN --JMP/JSR n(Ax,Dn) + skipFetch <= '1'; + END IF; + IF state="00" THEN + writePC <= '1'; + END IF; + set(hold_dwr) <= '1'; + IF set(get_ea_now)='1' THEN --jsr + IF exec(longaktion)='0' OR long_done='1' THEN + skipFetch <= '1'; + END IF; + setstate <="01"; + set(ea_to_pc) <= '1'; + END IF; + ELSE -- + CASE opcode(6 downto 0) IS + WHEN "1000000"|"1000001"|"1000010"|"1000011"|"1000100"|"1000101"|"1000110"|"1000111"| --trap + "1001000"|"1001001"|"1001010"|"1001011"|"1001100"|"1001101"|"1001110"|"1001111" => --trap + trap_trap <='1'; + trapmake <= '1'; + WHEN "1010000"|"1010001"|"1010010"|"1010011"|"1010100"|"1010101"|"1010110"|"1010111"=> --link + datatype <= "10"; + set_exec(opcADD) <= '1'; --for displacement + set_exec(Regwrena) <= '1'; + set(no_Flags) <= '1'; + IF decodeOPC='1' THEN + next_micro_state <= link1; + set(presub) <= '1'; + setstackaddr <='1'; + set(mem_addsub) <= '1'; + source_lowbits <= '1'; + source_areg <= '1'; + set(store_ea_data) <= '1'; + END IF; + + WHEN "1011000"|"1011001"|"1011010"|"1011011"|"1011100"|"1011101"|"1011110"|"1011111" => --unlink + datatype <= "10"; + set_exec(Regwrena) <= '1'; + set_exec(opcMOVE) <= '1'; + set(no_Flags) <= '1'; + IF decodeOPC='1' THEN + setstate <= "01"; + next_micro_state <= unlink1; + set(opcMOVE) <= '1'; + set(Regwrena) <= '1'; + setstackaddr <='1'; + source_lowbits <= '1'; + source_areg <= '1'; + END IF; + + WHEN "1100000"|"1100001"|"1100010"|"1100011"|"1100100"|"1100101"|"1100110"|"1100111" => --move An,USP + IF SVmode='1' THEN +-- set(no_Flags) <= '1'; + set(to_USP) <= '1'; + source_lowbits <= '1'; + source_areg <= '1'; + datatype <= "10"; + ELSE + trap_priv <= '1'; + trapmake <= '1'; + END IF; + WHEN "1101000"|"1101001"|"1101010"|"1101011"|"1101100"|"1101101"|"1101110"|"1101111" => --move USP,An + IF SVmode='1' THEN +-- set(no_Flags) <= '1'; + set(from_USP) <= '1'; + datatype <= "10"; + set_exec(Regwrena) <= '1'; + ELSE + trap_priv <= '1'; + trapmake <= '1'; + END IF; + + WHEN "1110000" => --reset + IF SVmode='0' THEN + trap_priv <= '1'; + trapmake <= '1'; + ELSE + set(opcRESET) <= '1'; + IF decodeOPC='1' THEN + set(ld_rot_cnt) <= '1'; + set_rot_cnt <= "000000"; + END IF; + END IF; + + WHEN "1110001" => --nop + + WHEN "1110010" => --stop + IF SVmode='0' THEN + trap_priv <= '1'; + trapmake <= '1'; + ELSE + IF decodeOPC='1' THEN + setnextpass <= '1'; + set_stop <= '1'; + END IF; + IF stop='1' THEN + skipFetch <= '1'; + END IF; + + END IF; + + WHEN "1110011"|"1110111" => --rte/rtr + IF SVmode='1' OR opcode(2)='1' THEN + IF decodeOPC='1' THEN + setstate <= "10"; + set(postadd) <= '1'; + setstackaddr <= '1'; + IF opcode(2)='1' THEN + set(directCCR) <= '1'; + ELSE + set(directSR) <= '1'; + END IF; + next_micro_state <= rte1; + END IF; + ELSE + trap_priv <= '1'; + trapmake <= '1'; + END IF; + + WHEN "1110101" => --rts + datatype <= "10"; + IF decodeOPC='1' THEN + setstate <= "10"; + set(postadd) <= '1'; + setstackaddr <= '1'; + set(direct_delta) <= '1'; + set(directPC) <= '1'; + next_micro_state <= nopnop; + END IF; + + WHEN "1110110" => --trapv + IF decodeOPC='1' THEN + setstate <= "01"; + END IF; + IF Flags(1)='1' AND state="01" THEN + trap_trapv <= '1'; + trapmake <= '1'; + END IF; + + WHEN "1111010"|"1111011" => --movec + IF VBR_Stackframe=0 OR (cpu(0)='0' AND VBR_Stackframe=2) THEN + trap_illegal <= '1'; + trapmake <= '1'; + ELSIF SVmode='0' THEN + trap_priv <= '1'; + trapmake <= '1'; + ELSE + datatype <= "10"; --Long + IF last_data_read(11 downto 0)=X"800" THEN + set(from_USP) <= '1'; + IF opcode(0)='1' THEN + set(to_USP) <= '1'; + END IF; + END IF; + IF opcode(0)='0' THEN + set_exec(movec_rd) <= '1'; + ELSE + set_exec(movec_wr) <= '1'; + END IF; + IF decodeOPC='1' THEN + next_micro_state <= movec1; + getbrief <='1'; + END IF; + END IF; + + WHEN OTHERS => + trap_illegal <= '1'; + trapmake <= '1'; + END CASE; + END IF; + WHEN OTHERS => NULL; + END CASE; + END IF; +-- +---- 0101 ---------------------------------------------------------------------------- + WHEN "0101" => --subq, addq + + IF opcode(7 downto 6)="11" THEN --dbcc + IF opcode(5 downto 3)="001" THEN --dbcc + IF decodeOPC='1' THEN + next_micro_state <= dbcc1; + set(OP2out_one) <= '1'; + data_is_source <= '1'; + END IF; + ELSE --Scc + datatype <= "00"; --Byte + ea_build_now <= '1'; + write_back <= '1'; + set_exec(opcScc) <= '1'; + IF cpu(0)='1' AND state="10" THEN + skipFetch <= '1'; + END IF; + IF opcode(5 downto 4)="00" THEN + set_exec(Regwrena) <= '1'; + END IF; + END IF; + ELSE --addq, subq + ea_build_now <= '1'; + IF opcode(5 downto 3)="001" THEN + set(no_Flags) <= '1'; + END IF; + IF opcode(8)='1' THEN + set(addsub) <= '1'; + END IF; + write_back <= '1'; + set_exec(opcADDQ) <= '1'; + set_exec(opcADD) <= '1'; + set_exec(ea_data_OP1) <= '1'; + IF opcode(5 downto 4)="00" THEN + set_exec(Regwrena) <= '1'; + END IF; + END IF; +-- +---- 0110 ---------------------------------------------------------------------------- + WHEN "0110" => --bra,bsr,bcc + datatype <= "10"; + + IF micro_state=idle THEN + IF opcode(11 downto 8)="0001" THEN --bsr + set(presub) <= '1'; + setstackaddr <='1'; + IF opcode(7 downto 0)="11111111" THEN + next_micro_state <= bsr2; + set(longaktion) <= '1'; + ELSIF opcode(7 downto 0)="00000000" THEN + next_micro_state <= bsr2; + ELSE + next_micro_state <= bsr1; + setstate <= "11"; + writePC <= '1'; + END IF; + ELSE --bra + IF opcode(7 downto 0)="11111111" THEN + next_micro_state <= bra1; + set(longaktion) <= '1'; + ELSIF opcode(7 downto 0)="00000000" THEN + next_micro_state <= bra1; + ELSE + setstate <= "01"; + next_micro_state <= bra1; + END IF; + END IF; + END IF; + +-- 0111 ---------------------------------------------------------------------------- + WHEN "0111" => --moveq +-- IF opcode(8)='0' THEN -- Cloanto's Amiga Forver ROMs have mangled movq instructions with a 1 here... + IF trap_interrupt='0' AND trap_trace='0' THEN + datatype <= "10"; --Long + set_exec(Regwrena) <= '1'; + set_exec(opcMOVEQ) <= '1'; + set_exec(opcMOVE) <= '1'; + dest_hbits <= '1'; + END IF; +-- ELSE +-- trap_illegal <= '1'; +-- trapmake <= '1'; +-- END IF; + +---- 1000 ---------------------------------------------------------------------------- + WHEN "1000" => --or + IF opcode(7 downto 6)="11" THEN --divu, divs + IF DIV_Mode/=3 THEN + IF opcode(5 downto 4)="00" THEN --Dn, An + regdirectsource <= '1'; + END IF; + IF (micro_state=idle AND nextpass='1') OR (opcode(5 downto 4)="00" AND decodeOPC='1') THEN + setstate <="01"; + next_micro_state <= div1; + END IF; + ea_build_now <= '1'; + IF z_error='0' AND set_V_Flag='0' THEN + set_exec(Regwrena) <= '1'; + END IF; + source_lowbits <='1'; + IF nextpass='1' OR (opcode(5 downto 4)="00" AND decodeOPC='1') THEN + dest_hbits <= '1'; + END IF; + datatype <= "01"; + ELSE + trap_illegal <= '1'; + trapmake <= '1'; + END IF; + + ELSIF opcode(8)='1' AND opcode(5 downto 4)="00" THEN --sbcd, pack , unpack + IF opcode(7 downto 6)="00" THEN --sbcd + build_bcd <= '1'; + set_exec(opcADD) <= '1'; + set_exec(opcSBCD) <= '1'; + ELSIF cpu(1)='1' AND (opcode(7 downto 6)="01" OR opcode(7 downto 6)="10") THEN --pack, unpack + datatype <= "01"; --Word + set_exec(opcPACK) <= '1'; + set(no_Flags) <= '1'; -- this command modifies no flags + + -- immediate value is kept in op1 + -- source value is in op2 + + -- xyz + if opcode(3)='0' then -- R/M bit = 0 -> Dy->Dy, 1 -(Ax),-(Ay) + dest_hbits <='1'; -- dest register is encoded in bits 9-11 + source_lowbits <= '1'; -- source register is encoded in bits 0-2 + + set_exec(Regwrena) <= '1'; -- write result into register + set_exec(ea_data_OP1) <= '1'; -- immediate value goes into op2 + set(hold_dwr) <= '1'; + + -- pack writes a byte only + IF opcode(7 downto 6) = "01" THEN + datatype <= "00"; --Byte + ELSE + datatype <= "01"; --Word + END IF; + + IF decodeOPC='1' THEN + next_micro_state <= nop; + set_direct_data <= '1'; + END IF; + else + set_exec(ea_data_OP1) <= '1'; + source_lowbits <= '1'; -- source register is encoded in bits 0-2 + + IF decodeOPC='1' THEN + -- first step: read source value + IF opcode(7 downto 6) = "10" THEN -- UNPK reads a byte + datatype <= "00"; -- Byte + END IF; + set_direct_data <= '1'; + setstate <= "10"; + set(update_ld) <= '1'; + set(presub) <= '1'; + next_micro_state <= pack1; + dest_areg <= '1'; --??? + end IF; + end IF; + ELSE + trap_illegal <= '1'; + trapmake <= '1'; + END IF; + ELSE --or + set_exec(opcOR) <= '1'; + build_logical <= '1'; + END IF; + +---- 1001, 1101 ----------------------------------------------------------------------- + WHEN "1001"|"1101" => --sub, add + set_exec(opcADD) <= '1'; + ea_build_now <= '1'; + IF opcode(14)='0' THEN + set(addsub) <= '1'; + END IF; + IF opcode(7 downto 6)="11" THEN -- --adda, suba + IF opcode(8)='0' THEN --adda.w, suba.w + datatype <= "01"; --Word + END IF; + set_exec(Regwrena) <= '1'; + source_lowbits <='1'; + IF opcode(3)='1' THEN + source_areg <= '1'; + END IF; + set(no_Flags) <= '1'; + IF setexecOPC='1' THEN + dest_areg <='1'; + dest_hbits <= '1'; + END IF; + ELSE + IF opcode(8)='1' AND opcode(5 downto 4)="00" THEN --addx, subx + build_bcd <= '1'; + ELSE --sub, add + build_logical <= '1'; + END IF; + END IF; + +-- +---- 1010 ---------------------------------------------------------------------------- + WHEN "1010" => --Trap 1010 + trap_1010 <= '1'; + trapmake <= '1'; +---- 1011 ---------------------------------------------------------------------------- + WHEN "1011" => --eor, cmp + ea_build_now <= '1'; + IF opcode(7 downto 6)="11" THEN --CMPA + IF opcode(8)='0' THEN --cmpa.w + datatype <= "01"; --Word + set_exec(opcCPMAW) <= '1'; + END IF; + set_exec(opcCMP) <= '1'; + IF setexecOPC='1' THEN + source_lowbits <='1'; + IF opcode(3)='1' THEN + source_areg <= '1'; + END IF; + dest_areg <='1'; + dest_hbits <= '1'; + END IF; + set(addsub) <= '1'; + ELSE + IF opcode(8)='1' THEN + IF opcode(5 downto 3)="001" THEN --cmpm + set_exec(opcCMP) <= '1'; + IF decodeOPC='1' THEN + setstate <= "10"; + set(update_ld) <= '1'; + set(postadd) <= '1'; + next_micro_state <= cmpm; + END IF; + set_exec(ea_data_OP1) <= '1'; + set(addsub) <= '1'; + ELSE --EOR + build_logical <= '1'; + set_exec(opcEOR) <= '1'; + END IF; + ELSE --CMP + build_logical <= '1'; + set_exec(opcCMP) <= '1'; + set(addsub) <= '1'; + END IF; + END IF; +-- +---- 1100 ---------------------------------------------------------------------------- + WHEN "1100" => --and, exg + IF opcode(7 downto 6)="11" THEN --mulu, muls + IF MUL_Mode/=3 THEN + IF opcode(5 downto 4)="00" THEN --Dn, An + regdirectsource <= '1'; + END IF; + IF (micro_state=idle AND nextpass='1') OR (opcode(5 downto 4)="00" AND decodeOPC='1') THEN + setstate <="01"; + set(ld_rot_cnt) <= '1'; + next_micro_state <= mul1; + END IF; + ea_build_now <= '1'; + set_exec(Regwrena) <= '1'; + source_lowbits <='1'; + IF (nextpass='1') OR (opcode(5 downto 4)="00" AND decodeOPC='1') THEN + dest_hbits <= '1'; + END IF; + datatype <= "01"; + ELSE + trap_illegal <= '1'; + trapmake <= '1'; + END IF; + + ELSIF opcode(8)='1' AND opcode(5 downto 4)="00" THEN --exg, abcd + IF opcode(7 downto 6)="00" THEN --abcd + build_bcd <= '1'; + set_exec(opcADD) <= '1'; + set_exec(opcABCD) <= '1'; + ELSE --exg + datatype <= "10"; + set(Regwrena) <= '1'; + set(exg) <= '1'; + IF opcode(6)='1' AND opcode(3)='1' THEN + dest_areg <= '1'; + source_areg <= '1'; + END IF; + IF decodeOPC='1' THEN + setstate <= "01"; + ELSE + dest_hbits <= '1'; + END IF; + END IF; + ELSE --and + set_exec(opcAND) <= '1'; + build_logical <= '1'; + END IF; +-- +---- 1110 ---------------------------------------------------------------------------- + WHEN "1110" => --rotation / bitfield + IF opcode(7 downto 6)="11" THEN + IF opcode(11)='0' THEN + set_exec(opcROT) <= '1'; + ea_build_now <= '1'; + datatype <= "01"; + set_rot_bits <= opcode(10 downto 9); + set_exec(ea_data_OP1) <= '1'; + write_back <= '1'; + ELSE --bitfield + IF BitField=0 OR (cpu(1)='0' AND BitField=2) THEN + trap_illegal <= '1'; + trapmake <= '1'; + ELSE + IF decodeOPC='1' THEN + next_micro_state <= nop; + set(get_2ndOPC) <= '1'; + set(ea_build) <= '1'; + END IF; + set_exec(opcBF) <= '1'; + IF opcode(10)='1' OR opcode(8)='0' THEN + set_exec(opcBFwb) <= '1'; + IF opcode(10 downto 8)/="111" THEN -- bfins + set_exec(ea_data_OP2) <= '1'; -- for the flags + END IF; + set_exec(ea_data_OP1) <= '1'; + END IF; + + -- BFCHG, BFCLR, BFSET, BFINS + IF opcode(10 downto 8)="010" OR opcode(10 downto 8)="100" OR opcode(10 downto 8)="110" OR opcode(10 downto 8)="111" THEN + write_back <= '1'; + END IF; + ea_only <= '1'; + -- BFEXTU, BFEXTS, BFFFO + IF opcode(10 downto 8)="001" OR opcode(10 downto 8)="011" OR opcode(10 downto 8)="101" THEN + set_exec(Regwrena) <= '1'; + END IF; + -- register destination + IF opcode(4 downto 3)="00" THEN + set_exec(Regwrena) <= '1'; + IF exec(ea_build)='1' THEN + dest_2ndHbits <= '1'; + source_2ndLbits <= '1'; + set(get_bfoffset) <='1'; + setstate <= "01"; + END IF; + END IF; + IF set(get_ea_now)='1' THEN + setstate <= "01"; + END IF; + IF exec(get_ea_now)='1' THEN + dest_2ndHbits <= '1'; + source_2ndLbits <= '1'; + set(get_bfoffset) <='1'; + setstate <= "01"; + set(mem_addsub) <='1'; + next_micro_state <= bf1; + END IF; + +-- BFINS D1,D0 s2ndHbits < D0 +-- BFEXT D0,D1 sLbits >>D0 -> D1 d2ndHbits +-- BFINS D1,(A0) s2ndHbits < (A0) +-- BFEXT (A0),D1 >>(A0) -> D1 d2ndHbits + IF setexecOPC='1' THEN + IF opcode(10 downto 8)="111" THEN --BFINS + source_2ndHbits <= '1'; + ELSIF opcode(10 downto 8)="001" or opcode(10 downto 8)="011" THEN --BFEXT + source_lowbits <= '1'; + dest_2ndHbits <= '1'; + END IF; + END IF; + END IF; + END IF; + ELSE + set_exec(opcROT) <= '1'; + set_rot_bits <= opcode(4 downto 3); + data_is_source <= '1'; + set_exec(Regwrena) <= '1'; + IF decodeOPC='1' THEN + IF opcode(5)='1' THEN + next_micro_state <= rota1; + set(ld_rot_cnt) <= '1'; + setstate <= "01"; + ELSE + set_rot_cnt(2 downto 0) <= opcode(11 downto 9); + IF opcode(11 downto 9)="000" THEN + set_rot_cnt(3) <='1'; + ELSE + set_rot_cnt(3) <='0'; + END IF; + END IF; + END IF; + END IF; +-- +---- ---------------------------------------------------------------------------- + WHEN OTHERS => + trap_1111 <= '1'; + trapmake <= '1'; + + END CASE; + +-- use for AND, OR, EOR, CMP + IF build_logical='1' THEN + ea_build_now <= '1'; + IF set_exec(opcCMP)='0' AND (opcode(8)='0' OR opcode(5 downto 4)="00" ) THEN + set_exec(Regwrena) <= '1'; + END IF; + IF opcode(8)='1' THEN + write_back <= '1'; + set_exec(ea_data_OP1) <= '1'; + ELSE + source_lowbits <='1'; + IF opcode(3)='1' THEN --use for cmp + source_areg <= '1'; + END IF; + IF setexecOPC='1' THEN + dest_hbits <= '1'; + END IF; + END IF; + END IF; + +-- use for ABCD, SBCD + IF build_bcd='1' THEN + set_exec(use_XZFlag) <= '1'; + set_exec(ea_data_OP1) <= '1'; + write_back <= '1'; + source_lowbits <='1'; + IF opcode(3)='1' THEN + IF decodeOPC='1' THEN + setstate <= "10"; + set(update_ld) <= '1'; + set(presub) <= '1'; + next_micro_state <= op_AxAy; + dest_areg <= '1'; --??? + END IF; + ELSE + dest_hbits <= '1'; + set_exec(Regwrena) <= '1'; + END IF; + END IF; + + +------------------------------------------------------------------------------ +------------------------------------------------------------------------------ + IF set_Z_error='1' THEN -- divu by zero + trapmake <= '1'; --wichtig for USP + IF trapd='0' THEN + writePC <= '1'; + END IF; + END IF; + +----------------------------------------------------------------------------- +-- execute microcode +----------------------------------------------------------------------------- + IF rising_edge(clk) THEN + IF Reset='1' THEN + micro_state <= ld_nn; + ELSIF clkena_lw='1' THEN + trapd <= trapmake; + micro_state <= next_micro_state; + END IF; + END IF; + + CASE micro_state IS + WHEN ld_nn => -- (nnnn).w/l=> + set(get_ea_now) <='1'; + setnextpass <= '1'; + set(addrlong) <= '1'; + + WHEN st_nn => -- =>(nnnn).w/l + setstate <= "11"; + set(addrlong) <= '1'; + next_micro_state <= nop; + + WHEN ld_dAn1 => -- d(An)=>, --d(PC)=> + set(get_ea_now) <='1'; + setdisp <= '1'; --word + setnextpass <= '1'; + + WHEN ld_AnXn1 => -- d(An,Xn)=>, --d(PC,Xn)=> + IF brief(8)='0' OR extAddr_Mode=0 OR (cpu(1)='0' AND extAddr_Mode=2) THEN + -- mikej brief extension word only + setdisp <= '1'; --byte + setdispbyte <= '1'; + setstate <= "01"; + set(briefext) <= '1'; + next_micro_state <= ld_AnXn2; + ELSE + IF brief(7)='1'THEN --suppress Base + set_suppress_base <= '1'; + ELSIF exec(dispouter)='1' THEN + set(dispouter) <= '1'; + END IF; + IF brief(5)='0' THEN --NULL Base Displacement + setstate <= "01"; + ELSE --WORD Base Displacement + IF brief(4)='1' THEN + set(longaktion) <= '1'; --LONG Base Displacement + END IF; + END IF; + next_micro_state <= ld_229_1; + END IF; + + WHEN ld_AnXn2 => + set(get_ea_now) <='1'; + setdisp <= '1'; --brief + setnextpass <= '1'; + +------------------------------------------------------------------------------------- + + WHEN ld_229_1 => -- (bd,An,Xn)=>, --(bd,PC,Xn)=> + IF brief(5)='1' THEN --Base Displacement + setdisp <= '1'; --add last_data_read + END IF; + IF brief(6)='0' AND brief(2)='0' THEN --Preindex or Index + set(briefext) <= '1'; + setstate <= "01"; + IF brief(1 downto 0)="00" THEN + next_micro_state <= ld_AnXn2; + ELSE + next_micro_state <= ld_229_2; + END IF; + ELSE + IF brief(1 downto 0)="00" THEN + set(get_ea_now) <='1'; + setnextpass <= '1'; + ELSE + setstate <= "10"; + set(longaktion) <= '1'; + next_micro_state <= ld_229_3; + END IF; + END IF; + + WHEN ld_229_2 => -- (bd,An,Xn)=>, --(bd,PC,Xn)=> + setdisp <= '1'; -- add Index + setstate <= "10"; + set(longaktion) <= '1'; + next_micro_state <= ld_229_3; + + WHEN ld_229_3 => -- (bd,An,Xn)=>, --(bd,PC,Xn)=> + set_suppress_base <= '1'; + set(dispouter) <= '1'; + IF brief(1)='0' THEN --NULL Outer Displacement + setstate <= "01"; + ELSE --WORD Outer Displacement + IF brief(0)='1' THEN + set(longaktion) <= '1'; --LONG Outer Displacement + END IF; + END IF; + next_micro_state <= ld_229_4; + + WHEN ld_229_4 => -- (bd,An,Xn)=>, --(bd,PC,Xn)=> + IF brief(1)='1' THEN -- Outer Displacement + setdisp <= '1'; --add last_data_read + END IF; + IF brief(6)='0' AND brief(2)='1' THEN --Postindex + set(briefext) <= '1'; + setstate <= "01"; + next_micro_state <= ld_AnXn2; + ELSE + set(get_ea_now) <='1'; + setnextpass <= '1'; + END IF; + +---------------------------------------------------------------------------------------- + WHEN st_dAn1 => -- =>d(An) + setstate <= "11"; + setdisp <= '1'; --word + next_micro_state <= nop; + + WHEN st_AnXn1 => -- =>d(An,Xn) + IF brief(8)='0' OR extAddr_Mode=0 OR (cpu(1)='0' AND extAddr_Mode=2) THEN + setdisp <= '1'; --byte + setdispbyte <= '1'; + setstate <= "01"; + set(briefext) <= '1'; + next_micro_state <= st_AnXn2; + ELSE + IF brief(7)='1'THEN --suppress Base + set_suppress_base <= '1'; +-- ELSIF exec(dispouter)='1' THEN +-- set(dispouter) <= '1'; + END IF; + IF brief(5)='0' THEN --NULL Base Displacement + setstate <= "01"; + ELSE --WORD Base Displacement + IF brief(4)='1' THEN + set(longaktion) <= '1'; --LONG Base Displacement + END IF; + END IF; + next_micro_state <= st_229_1; + END IF; + + WHEN st_AnXn2 => + setstate <= "11"; + setdisp <= '1'; --brief + next_micro_state <= nop; + +------------------------------------------------------------------------------------- + + WHEN st_229_1 => -- (bd,An,Xn)=>, --(bd,PC,Xn)=> + IF brief(5)='1' THEN --Base Displacement + setdisp <= '1'; --add last_data_read + END IF; + IF brief(6)='0' AND brief(2)='0' THEN --Preindex or Index + set(briefext) <= '1'; + setstate <= "01"; + IF brief(1 downto 0)="00" THEN + next_micro_state <= st_AnXn2; + ELSE + next_micro_state <= st_229_2; + END IF; + ELSE + IF brief(1 downto 0)="00" THEN + setstate <= "11"; + next_micro_state <= nop; + ELSE + set(hold_dwr) <= '1'; + setstate <= "10"; + set(longaktion) <= '1'; + next_micro_state <= st_229_3; + END IF; + END IF; + + WHEN st_229_2 => -- (bd,An,Xn)=>, --(bd,PC,Xn)=> + setdisp <= '1'; -- add Index + set(hold_dwr) <= '1'; + setstate <= "10"; + set(longaktion) <= '1'; + next_micro_state <= st_229_3; + + WHEN st_229_3 => -- (bd,An,Xn)=>, --(bd,PC,Xn)=> + set(hold_dwr) <= '1'; + set_suppress_base <= '1'; + set(dispouter) <= '1'; + IF brief(1)='0' THEN --NULL Outer Displacement + setstate <= "01"; + ELSE --WORD Outer Displacement + IF brief(0)='1' THEN + set(longaktion) <= '1'; --LONG Outer Displacement + END IF; + END IF; + next_micro_state <= st_229_4; + + WHEN st_229_4 => -- (bd,An,Xn)=>, --(bd,PC,Xn)=> + set(hold_dwr) <= '1'; + IF brief(1)='1' THEN -- Outer Displacement + setdisp <= '1'; --add last_data_read + END IF; + IF brief(6)='0' AND brief(2)='1' THEN --Postindex + set(briefext) <= '1'; + setstate <= "01"; + next_micro_state <= st_AnXn2; + ELSE + setstate <= "11"; + next_micro_state <= nop; + END IF; + +---------------------------------------------------------------------------------------- + WHEN bra1 => --bra + IF exe_condition='1' THEN + TG68_PC_brw <= '1'; --pc+0000 + next_micro_state <= nop; + skipFetch <= '1'; + END IF; + + WHEN bsr1 => --bsr short + TG68_PC_brw <= '1'; + next_micro_state <= nop; + + WHEN bsr2 => --bsr + IF long_start='0' THEN + TG68_PC_brw <= '1'; + END IF; + skipFetch <= '1'; + set(longaktion) <= '1'; + writePC <= '1'; + setstate <= "11"; + next_micro_state <= nopnop; + setstackaddr <='1'; + WHEN nopnop => --bsr + next_micro_state <= nop; + + WHEN dbcc1 => --dbcc + IF exe_condition='0' THEN + Regwrena_now <= '1'; + IF c_out(1)='1' THEN + skipFetch <= '1'; + next_micro_state <= nop; + TG68_PC_brw <= '1'; + END IF; + END IF; + + WHEN movem1 => --movem + IF last_data_read(15 downto 0)/=X"0000" THEN + setstate <="01"; + IF opcode(5 downto 3)="100" THEN + set(mem_addsub) <= '1'; + END IF; + next_micro_state <= movem2; + END IF; + WHEN movem2 => --movem + IF movem_run='0' THEN + setstate <="01"; + ELSE + set(movem_action) <= '1'; + set(mem_addsub) <= '1'; + next_micro_state <= movem2; + IF opcode(10)='0' THEN + setstate <="11"; + set(write_reg) <= '1'; + ELSE + setstate <="10"; + END IF; + END IF; + + WHEN andi => --andi + IF opcode(5 downto 4)/="00" THEN + setnextpass <= '1'; + END IF; + + WHEN op_AxAy => -- op -(Ax),-(Ay) + set_direct_data <= '1'; + set(presub) <= '1'; + dest_hbits <= '1'; + dest_areg <= '1'; + setstate <= "10"; + + WHEN cmpm => -- cmpm (Ay)+,(Ax)+ + set_direct_data <= '1'; + set(postadd) <= '1'; + dest_hbits <= '1'; + dest_areg <= '1'; + setstate <= "10"; + + WHEN link1 => -- link + setstate <="11"; + source_areg <= '1'; + set(opcMOVE) <= '1'; + set(Regwrena) <= '1'; + next_micro_state <= link2; + WHEN link2 => -- link + setstackaddr <='1'; + set(ea_data_OP2) <= '1'; + + WHEN unlink1 => -- unlink + setstate <="10"; + setstackaddr <='1'; + set(postadd) <= '1'; + next_micro_state <= unlink2; + WHEN unlink2 => -- unlink + set(ea_data_OP2) <= '1'; + + WHEN trap0 => -- TRAP + set(presub) <= '1'; + setstackaddr <='1'; + setstate <= "11"; + IF VBR_Stackframe=1 OR (cpu(0)='1' AND VBR_Stackframe=2) THEN --68010 + set(writePC_add) <= '1'; + datatype <= "01"; +-- set_datatype <= "10"; + next_micro_state <= trap1; + ELSE + IF trap_interrupt='1' OR trap_trace='1' OR trap_berr='1' THEN + writePC <= '1'; + END IF; + datatype <= "10"; + next_micro_state <= trap2; + END IF; + WHEN trap1 => -- TRAP + IF trap_interrupt='1' OR trap_trace='1' THEN + writePC <= '1'; + END IF; + set(presub) <= '1'; + setstackaddr <='1'; + setstate <= "11"; + datatype <= "10"; + next_micro_state <= trap2; + WHEN trap2 => -- TRAP + set(presub) <= '1'; + setstackaddr <='1'; + setstate <= "11"; + datatype <= "01"; + writeSR <= '1'; + IF trap_berr='1' THEN + next_micro_state <= trap4; + ELSE + next_micro_state <= trap3; + END IF; + WHEN trap3 => -- TRAP + set_vectoraddr <= '1'; + datatype <= "10"; + set(direct_delta) <= '1'; + set(directPC) <= '1'; + setstate <= "10"; + next_micro_state <= nopnop; + WHEN trap4 => -- TRAP + set(presub) <= '1'; + setstackaddr <='1'; + setstate <= "11"; + datatype <= "01"; + writeSR <= '1'; + next_micro_state <= trap5; + WHEN trap5 => -- TRAP + set(presub) <= '1'; + setstackaddr <='1'; + setstate <= "11"; + datatype <= "10"; + writeSR <= '1'; + next_micro_state <= trap6; + WHEN trap6 => -- TRAP + set(presub) <= '1'; + setstackaddr <='1'; + setstate <= "11"; + datatype <= "01"; + writeSR <= '1'; + next_micro_state <= trap3; + WHEN rte1 => -- RTE + datatype <= "10"; + setstate <= "10"; + set(postadd) <= '1'; + setstackaddr <= '1'; + IF VBR_Stackframe=0 OR (cpu(0)='0' AND VBR_Stackframe=2) THEN + set(direct_delta) <= '1'; + END IF; + set(directPC) <= '1'; + next_micro_state <= rte2; + WHEN rte2 => -- RTE + datatype <= "01"; + set(update_FC) <= '1'; + IF VBR_Stackframe=1 OR (cpu(0)='1' AND VBR_Stackframe=2) THEN + setstate <= "10"; + set(postadd) <= '1'; + setstackaddr <= '1'; + next_micro_state <= rte3; + ELSE + next_micro_state <= nop; + END IF; + WHEN rte3 => -- RTE + next_micro_state <= nop; +-- set(update_FC) <= '1'; + + WHEN movec1 => -- MOVEC + set(briefext) <= '1'; + set_writePCbig <='1'; + IF (brief(11 downto 0)=X"000" OR brief(11 downto 0)=X"001" OR brief(11 downto 0)=X"800" OR brief(11 downto 0)=X"801") OR + (cpu(1)='1' AND (brief(11 downto 0)=X"002" OR brief(11 downto 0)=X"802" OR brief(11 downto 0)=X"803" OR brief(11 downto 0)=X"804")) THEN + IF opcode(0)='0' THEN + set(Regwrena) <= '1'; + END IF; +-- ELSIF brief(11 downto 0)=X"800"OR brief(11 downto 0)=X"001" OR brief(11 downto 0)=X"000" THEN +-- trap_addr_error <= '1'; +-- trapmake <= '1'; + ELSE + trap_illegal <= '1'; + trapmake <= '1'; + END IF; + + WHEN movep1 => -- MOVEP d(An) + setdisp <= '1'; + set(mem_addsub) <= '1'; + set(mem_byte) <= '1'; + set(OP1addr) <= '1'; + IF opcode(6)='1' THEN + set(movepl) <= '1'; + END IF; + IF opcode(7)='0' THEN + setstate <= "10"; + ELSE + setstate <= "11"; + END IF; + next_micro_state <= movep2; + WHEN movep2 => + IF opcode(6)='1' THEN + set(mem_addsub) <= '1'; + set(OP1addr) <= '1'; + END IF; + IF opcode(7)='0' THEN + setstate <= "10"; + ELSE + setstate <= "11"; + END IF; + next_micro_state <= movep3; + WHEN movep3 => + IF opcode(6)='1' THEN + set(mem_addsub) <= '1'; + set(OP1addr) <= '1'; + set(mem_byte) <= '1'; + IF opcode(7)='0' THEN + setstate <= "10"; + ELSE + setstate <= "11"; + END IF; + next_micro_state <= movep4; + ELSE + datatype <= "01"; --Word + END IF; + WHEN movep4 => + IF opcode(7)='0' THEN + setstate <= "10"; + ELSE + setstate <= "11"; + END IF; + next_micro_state <= movep5; + WHEN movep5 => + datatype <= "10"; --Long + + WHEN mul1 => -- mulu + IF opcode(15)='1' OR MUL_Mode=0 THEN + set_rot_cnt <= "001110"; + ELSE + set_rot_cnt <= "011110"; + END IF; + setstate <="01"; + next_micro_state <= mul2; + WHEN mul2 => -- mulu + setstate <="01"; + IF rot_cnt="00001" THEN + next_micro_state <= mul_end1; + ELSE + next_micro_state <= mul2; + END IF; + WHEN mul_end1 => -- mulu + datatype <= "10"; + set(opcMULU) <= '1'; + IF opcode(15)='0' AND (MUL_Mode=1 OR MUL_Mode=2) THEN + dest_2ndHbits <= '1'; + source_2ndLbits <= '1';--??? + set(write_lowlong) <= '1'; + IF sndOPC(10)='1' THEN + setstate <="01"; + next_micro_state <= mul_end2; + END IF; + set(Regwrena) <= '1'; + END IF; + datatype <= "10"; + WHEN mul_end2 => -- divu + set(write_reminder) <= '1'; + set(Regwrena) <= '1'; + set(opcMULU) <= '1'; + + WHEN div1 => -- divu + setstate <="01"; + next_micro_state <= div2; + WHEN div2 => -- divu + IF (OP2out(31 downto 16)=x"0000" OR opcode(15)='1' OR DIV_Mode=0) AND OP2out(15 downto 0)=x"0000" THEN --div zero + set_Z_error <= '1'; + ELSE + next_micro_state <= div3; + END IF; + set(ld_rot_cnt) <= '1'; + setstate <="01"; + WHEN div3 => -- divu + IF opcode(15)='1' OR DIV_Mode=0 THEN + set_rot_cnt <= "001101"; + ELSE + set_rot_cnt <= "011101"; + END IF; + setstate <="01"; + next_micro_state <= div4; + WHEN div4 => -- divu + setstate <="01"; + IF rot_cnt="00001" THEN + next_micro_state <= div_end1; + ELSE + next_micro_state <= div4; + END IF; + WHEN div_end1 => -- divu + IF opcode(15)='0' AND (DIV_Mode=1 OR DIV_Mode=2) THEN + set(write_reminder) <= '1'; + next_micro_state <= div_end2; + setstate <="01"; + END IF; + set(opcDIVU) <= '1'; + datatype <= "10"; + WHEN div_end2 => -- divu + dest_2ndHbits <= '1'; + source_2ndLbits <= '1';--??? + set(opcDIVU) <= '1'; + + WHEN rota1 => + IF OP2out(5 downto 0)/="000000" THEN + set_rot_cnt <= OP2out(5 downto 0); + ELSE + set_exec(rot_nop) <= '1'; + END IF; + + WHEN bf1 => + setstate <="10"; + + when pack1 => + -- result computation + IF opcode(7 downto 6) = "10" THEN -- UNPK reads a byte + datatype <= "00"; -- Byte + END IF; + set(ea_data_OP2) <= '1'; + set(opcPACK) <= '1'; + next_micro_state <= pack2; + + when pack2 => + -- write result + IF opcode(7 downto 6) = "01" THEN -- PACK writes a byte + datatype <= "00"; + END IF; + set(presub) <= '1'; + setstate <= "11"; + dest_hbits <= '1'; + dest_areg <= '1'; + next_micro_state <= pack3; + + when pack3 => + -- this is just to keep datatype == 00 + -- for byte writes + -- write result + IF opcode(7 downto 6) = "01" THEN -- PACK writes a byte + datatype <= "00"; + END IF; + + WHEN OTHERS => NULL; + END CASE; + END PROCESS; + +----------------------------------------------------------------------------- +-- MOVEC +----------------------------------------------------------------------------- +PROCESS (clk, VBR, CACR, brief) + BEGIN + IF rising_edge(clk) THEN + IF Reset = '1' THEN + VBR <= (OTHERS => '0'); + CACR <= (OTHERS => '0'); + ELSIF clkena_lw='1' AND exec(movec_wr)='1' THEN + CASE brief(11 downto 0) IS + WHEN X"002" => CACR <= reg_QA(3 downto 0); + WHEN X"801" => VBR <= reg_QA; + WHEN OTHERS => NULL; + END CASE; + END IF; + END IF; + movec_data <= (OTHERS=>'0'); + CASE brief(11 downto 0) IS + WHEN X"002" => movec_data <= "0000000000000000000000000000" & (CACR AND "0011"); + WHEN X"801" => --IF VBR_Stackframe=1 OR (cpu(0)='1' AND VBR_Stackframe=2) THEN + movec_data <= VBR; + --END IF; + WHEN OTHERS => NULL; + END CASE; + END PROCESS; + + CACR_out <= CACR; + VBR_out <= VBR; + +----------------------------------------------------------------------------- +-- Conditions +----------------------------------------------------------------------------- +PROCESS (exe_opcode, Flags) + BEGIN + CASE exe_opcode(11 downto 8) IS + WHEN X"0" => exe_condition <= '1'; + WHEN X"1" => exe_condition <= '0'; + WHEN X"2" => exe_condition <= NOT Flags(0) AND NOT Flags(2); + WHEN X"3" => exe_condition <= Flags(0) OR Flags(2); + WHEN X"4" => exe_condition <= NOT Flags(0); + WHEN X"5" => exe_condition <= Flags(0); + WHEN X"6" => exe_condition <= NOT Flags(2); + WHEN X"7" => exe_condition <= Flags(2); + WHEN X"8" => exe_condition <= NOT Flags(1); + WHEN X"9" => exe_condition <= Flags(1); + WHEN X"a" => exe_condition <= NOT Flags(3); + WHEN X"b" => exe_condition <= Flags(3); + WHEN X"c" => exe_condition <= (Flags(3) AND Flags(1)) OR (NOT Flags(3) AND NOT Flags(1)); + WHEN X"d" => exe_condition <= (Flags(3) AND NOT Flags(1)) OR (NOT Flags(3) AND Flags(1)); + WHEN X"e" => exe_condition <= (Flags(3) AND Flags(1) AND NOT Flags(2)) OR (NOT Flags(3) AND NOT Flags(1) AND NOT Flags(2)); + WHEN X"f" => exe_condition <= (Flags(3) AND NOT Flags(1)) OR (NOT Flags(3) AND Flags(1)) OR Flags(2); + WHEN OTHERS => NULL; + END CASE; + END PROCESS; + +----------------------------------------------------------------------------- +-- Movem +----------------------------------------------------------------------------- +PROCESS (clk) + BEGIN + IF rising_edge(clk) THEN + IF clkena_lw='1' THEN + movem_actiond <= exec(movem_action); + IF decodeOPC='1' THEN + sndOPC <= data_read(15 downto 0); + ELSIF exec(movem_action)='1' OR set(movem_action) ='1' THEN + CASE movem_regaddr IS + WHEN "0000" => sndOPC(0) <= '0'; + WHEN "0001" => sndOPC(1) <= '0'; + WHEN "0010" => sndOPC(2) <= '0'; + WHEN "0011" => sndOPC(3) <= '0'; + WHEN "0100" => sndOPC(4) <= '0'; + WHEN "0101" => sndOPC(5) <= '0'; + WHEN "0110" => sndOPC(6) <= '0'; + WHEN "0111" => sndOPC(7) <= '0'; + WHEN "1000" => sndOPC(8) <= '0'; + WHEN "1001" => sndOPC(9) <= '0'; + WHEN "1010" => sndOPC(10) <= '0'; + WHEN "1011" => sndOPC(11) <= '0'; + WHEN "1100" => sndOPC(12) <= '0'; + WHEN "1101" => sndOPC(13) <= '0'; + WHEN "1110" => sndOPC(14) <= '0'; + WHEN "1111" => sndOPC(15) <= '0'; + WHEN OTHERS => NULL; + END CASE; + END IF; + END IF; + END IF; + END PROCESS; + +PROCESS (sndOPC, movem_mux) + BEGIN + movem_regaddr <="0000"; + movem_run <= '1'; + IF sndOPC(3 downto 0)="0000" THEN + IF sndOPC(7 downto 4)="0000" THEN + movem_regaddr(3) <= '1'; + IF sndOPC(11 downto 8)="0000" THEN + IF sndOPC(15 downto 12)="0000" THEN + movem_run <= '0'; + END IF; + movem_regaddr(2) <= '1'; + movem_mux <= sndOPC(15 downto 12); + ELSE + movem_mux <= sndOPC(11 downto 8); + END IF; + ELSE + movem_mux <= sndOPC(7 downto 4); + movem_regaddr(2) <= '1'; + END IF; + ELSE + movem_mux <= sndOPC(3 downto 0); + END IF; + IF movem_mux(1 downto 0)="00" THEN + movem_regaddr(1) <= '1'; + IF movem_mux(2)='0' THEN + movem_regaddr(0) <= '1'; + END IF; + ELSE + IF movem_mux(0)='0' THEN + movem_regaddr(0) <= '1'; + END IF; + END IF; + END PROCESS; + +--When the instruction has completed, the decremented address +--register contains the address of the last operand stored. For +--the MC68020, MC68030, and MC68040, if the addressing +--register is also moved to memory, the value written is the +--initial register value decremented by the size of the oper- +--ation. The MC68000 writes the initial register value +--(not decremented). + +END; diff --git a/addrController_top.v b/addrController_top.v new file mode 100644 index 0000000..cccb40f --- /dev/null +++ b/addrController_top.v @@ -0,0 +1,151 @@ +module addrController_top +( + // clocks: + input clk, + input cep, // 8.125 MHz CPU clock + input cen, // 8.125 MHz CPU clock + + // system config: + input turbo, // 0 = normal, 1 = faster + input configROMSize, // 0 = 64K ROM, 1 = 128K ROM + input [1:0] configRAMSize, // 0 = 128K, 1 = 512K, 2 = 1MB, 3 = 4MB RAM + + // 68000 CPU memory interface: + input [23:0] cpuAddr, + input _cpuUDS, + input _cpuLDS, + input _cpuRW, + + // RAM/ROM: + output [21:0] memoryAddr, + output _memoryUDS, + output _memoryLDS, + output _romOE, + output _ramOE, + output _ramWE, + output dioBusControl, + output cpuBusControl, + + // peripherals: + output selectSCSI, + output selectSCC, + output selectIWM, + output selectVIA, + + // video: + input _vblank, + input _hblank, + + input snd_alt, + output loadSound, + + // misc + input memoryOverlayOn, + + // interface to read dsk image from ram + input [21:0] dskReadAddrInt, + output dskReadAckInt, + input [21:0] dskReadAddrExt, + output dskReadAckExt +); + +// -------------- audio engine (may be moved into seperate module) --------------- +assign loadSound = audioReq & sndReadAck; + +reg [21:0] audioAddr; +reg audioReq; +always @(posedge clk) begin + reg vblankD; + reg hblankD; + reg swap; + reg sndReadAckD; + + sndReadAckD <= sndReadAck; + if(sndReadAckD & ~sndReadAck) begin // prepare for next audio cycle + vblankD <= _vblank; + hblankD <= _hblank; + audioReq <= 0; + + // falling adge of _vblank = begin of vblank phase + if(vblankD && !_vblank) swap <= 1; + + if(hblankD && !_hblank) begin + if(swap) audioAddr <= snd_alt ? 22'h3FA100 : 22'h3FFD00; + else audioAddr <= audioAddr + 22'd2; + swap <= 0; + audioReq <= 1; + end + end +end + +// interleaved RAM access for CPU and periphery +reg [3:0] cycle; +wire [1:0] busCycle = cycle[1:0]; +wire [1:0] subCycle = cycle[3:2]; +always @(posedge clk) if(cep) cycle <= cycle + 2'd1; + +assign cpuBusControl = turbo ? busCycle[0] : (busCycle == 1); +assign dioBusControl = (busCycle == 2); + +assign dskReadAckInt = dioBusControl && (subCycle == 0); +assign dskReadAckExt = dioBusControl && (subCycle == 1); +wire sndReadAck = (busCycle == 0); + + +// interconnects +wire selectRAM, selectROM; + +// RAM/ROM control signals +wire extraRomRead = dskReadAckInt || dskReadAckExt; +assign _romOE = ~(extraRomRead || (cpuBusControl && selectROM && _cpuRW)); + +assign _ramOE = ~(loadSound || (cpuBusControl && selectRAM && _cpuRW)); +assign _ramWE = ~(cpuBusControl && selectRAM && !_cpuRW); + +assign _memoryUDS = cpuBusControl ? _cpuUDS : 1'b0; +assign _memoryLDS = cpuBusControl ? _cpuLDS : 1'b0; +wire [21:0] addrMux = loadSound ? audioAddr : cpuAddr[21:0]; +wire [21:0] macAddr; +assign macAddr[15:0] = addrMux[15:0]; + +// video and sound always addresses ram +wire ram_access = (cpuBusControl && selectRAM) || loadSound; +wire rom_access = (cpuBusControl && selectROM); + +// simulate smaller RAM/ROM sizes +assign macAddr[16] = rom_access && configROMSize == 1'b0 ? 1'b0 : // force A16 to 0 for 64K ROM access + addrMux[16]; +assign macAddr[17] = ram_access && configRAMSize == 2'b00 ? 1'b0 : // force A17 to 0 for 128K RAM access + rom_access && configROMSize == 1'b1 ? 1'b0 : // force A17 to 0 for 128K ROM access + rom_access && configROMSize == 1'b0 ? 1'b1 : // force A17 to 1 for 64K ROM access (64K ROM image is at $20000) + addrMux[17]; +assign macAddr[18] = ram_access && configRAMSize == 2'b00 ? 1'b0 : // force A18 to 0 for 128K RAM access + rom_access ? 1'b0 : // force A18 to 0 for ROM access + addrMux[18]; +assign macAddr[19] = ram_access && configRAMSize[1] == 1'b0 ? 1'b0 : // force A19 to 0 for 128K or 512K RAM access + rom_access ? 1'b0 : // force A19 to 0 for ROM access + addrMux[19]; +assign macAddr[20] = ram_access && configRAMSize != 2'b11 ? 1'b0 : // force A20 to 0 for all but 4MB RAM access + rom_access ? 1'b0 : // force A20 to 0 for ROM access + addrMux[20]; +assign macAddr[21] = ram_access && configRAMSize != 2'b11 ? 1'b0 : // force A21 to 0 for all but 4MB RAM access + rom_access ? 1'b0 : // force A21 to 0 for ROM access + addrMux[21]; + +assign memoryAddr = + dskReadAckInt ? dskReadAddrInt + 22'h100000: // first dsk image at 1MB + dskReadAckExt ? dskReadAddrExt + 22'h200000: // second dsk image at 2MB + macAddr; + +// address decoding +addrDecoder ad( + .address(cpuAddr), + .memoryOverlayOn(memoryOverlayOn), + .selectRAM(selectRAM), + .selectROM(selectROM), + .selectSCSI(selectSCSI), + .selectSCC(selectSCC), + .selectIWM(selectIWM), + .selectVIA(selectVIA)); + +endmodule diff --git a/addrDecoder.v b/addrDecoder.v new file mode 100644 index 0000000..41d6083 --- /dev/null +++ b/addrDecoder.v @@ -0,0 +1,132 @@ +/* + ($000000 - $03FFFF) RAM 4MB, or Overlay ROM 4MB + + ($400000 - $4FFFFF) ROM 1MB + 64K Mac 128K/512K ROM is $400000 - $40FFFF + 128K Mac 512Ke/Plus ROM is $400000 - $41FFFF + If ROM is mirrored when A17 is 1, then SCSI is assumed to be unavailable + + ($580000 - $580FFF) SCSI (Mac Plus only, not implemented here) + + ($600000 - $7FFFFF) Overlay RAM 2MB + + ($9FFFF8 - $BFFFFF) SCC + The SCC is on the upper byte of the data bus, so you must use only even-addressed byte reads. + When writing, you must use only odd-addressed byte writes (the MC68000 puts your data on both bytes of the bus, so it works correctly). + A byte read of an odd SCC read address tries to reset the entire SCC. + A word access to any SCC address will shift the phase of the computer's high-frequency timing by 128 ns. + + ($9FFFF8) SCC read channel B control + ($9FFFFA) SCC read channel A control + ($9FFFFC) SCC read channel B data in/out + ($9FFFFE) SCC read channel A data in/out + + ($BFFFF9) SCC write channel B control + ($BFFFFB) SCC write channel A control + ($BFFFFD) SCC write channel B data in/out + ($BFFFFF) SCC write channel A data in/out + + ($DFE1FF - $DFFFFF) IWM + The IWM is on the lower byte of the data bus, so use odd-addressed byte accesses only. + The 16 IWM registers are {8'hDF, 8'b111xxxx1, 8'hFF}: + 0 $0 ph0L CA0 off (0) + 1 $200 ph0H CA0 on (1) + 2 $400 ph1L CA1 off (0) + 3 $600 ph1H CA1 on (1) + 4 $800 h2L CA2 off (0) + 5 $A00 ph2H CA2 on (1) + 6 $C00 ph3L LSTRB off (low) + 7 $E00 ph3H LSTRB on (high) + 8 $1000 mtrOff disk enable off + 9 $1200 mtrOn disk enable on + 10 $1400 intDrive select internal drive + 11 $1600 extDrive select external drive + 12 $1800 q6L Q6 off + 13 $1A00 q6H Q6 on + 14 $1C00 q7L Q7 off, read register + 15 $1E00 q7H Q7 on, write register + + ($EFE1FE - $EFFFFE) VIA + The VIA is on the upper byte of the data bus, so use even-addressed byte accesses only. + The 16 VIA registers are {8'hEF, 8'b111xxxx1, 8'hFE}: + 0 $0 vBufB register B + 1 $200 ????? not used? + 2 $400 vDirB register B direction register + 3 $600 vDirA register A direction register + 4 $800 vT1C timer 1 counter (low-order byte) + 5 $A00 vT1CH timer 1 counter (high-order byte) + 6 $C00 vT1L timer 1 latch (low-order byte) + 7 $E00 vT1LH timer 1 latch (high-order byte) + 8 $1000 vT2C timer 2 counter (low-order byte) + 9 $1200 vT2CH timer 2 counter (high-order byte) + 10 $1400 vSR shift register (keyboard) + 11 $1600 vACR auxiliary control register + 12 $1800 vPCR peripheral control register + 13 $1A00 vIFR interrupt flag register + 14 $1C00 vIER interrupt enable register + 15 $1E00 vBufA register A + + ($F00000 - $F00005) memory phase read test + + ($F80000 - $FFFFEF) space for test software + + ($FFFFF0 - $FFFFFF) interrupt vectors + + Note: This can all be decoded using only the highest 4 address bits, if SCSI, phase read test, and test software are not used. + 7 other address bits are used by peripherals to determine which register to access: + A12-A9 - IWM and VIA + A2-A0 - SCC + +*/ + +module addrDecoder( + input [23:0] address, + input memoryOverlayOn, + output reg selectRAM, + output reg selectROM, + output reg selectSCSI, + output reg selectSCC, + output reg selectIWM, + output reg selectVIA +); + + always @(*) begin + selectRAM = 0; + selectROM = 0; + selectSCSI = 0; + selectSCC = 0; + selectIWM = 0; + selectVIA = 0; + + casez (address[23:20]) + 4'b00??: begin + if (memoryOverlayOn == 0) + selectRAM = 1'b1; + else begin + if (address[23:20] == 0) begin + // Mac Plus: repeated images of overlay ROM only extend to $0F0000 + // Mac 512K: more repeated ROM images at $020000-$02FFFF + selectROM = 1'b1; + end + end + end + 4'b0100: + if( address[17] == 1'b0) // <- this detects SCSI!!! + selectROM = 1'b1; + 4'b0101: + if (address[19:12] == 8'h80) + selectSCSI = 1'b1; + 4'b0110: + if (memoryOverlayOn) + selectRAM = 1'b1; + 4'b10?1: + selectSCC = 1'b1; + 4'b1101: + selectIWM = 1'b1; + 4'b1110: + selectVIA = 1'b1; + default: + ; // select nothing + endcase + end +endmodule diff --git a/clean.bat b/clean.bat new file mode 100644 index 0000000..f328058 --- /dev/null +++ b/clean.bat @@ -0,0 +1,37 @@ +@echo off +del /s *.bak +del /s *.orig +del /s *.rej +del /s *~ +rmdir /s /q db +rmdir /s /q incremental_db +rmdir /s /q output_files +rmdir /s /q simulation +rmdir /s /q greybox_tmp +rmdir /s /q hc_output +rmdir /s /q .qsys_edit +rmdir /s /q hps_isw_handoff +rmdir /s /q sys\.qsys_edit +rmdir /s /q sys\vip +cd sys +for /d %%i in (*_sim) do rmdir /s /q "%%~nxi" +cd .. +for /d %%i in (*_sim) do rmdir /s /q "%%~nxi" +del build_id.v +del c5_pin_model_dump.txt +del PLLJ_PLLSPE_INFO.txt +del /s *.qws +del /s *.ppf +del /s *.ddb +del /s *.csv +del /s *.cmp +del /s *.sip +del /s *.spd +del /s *.bsf +del /s *.f +del /s *.sopcinfo +del /s *.xml +del /s new_rtl_netlist +del /s old_rtl_netlist + +pause diff --git a/dataController_top.v b/dataController_top.v new file mode 100644 index 0000000..19b2351 --- /dev/null +++ b/dataController_top.v @@ -0,0 +1,299 @@ +module dataController_top( + // clocks: + input clk, + input cep, + input cen, + + // system control: + input _systemReset, + + // 68000 CPU control: + output _cpuReset, + output [2:0] _cpuIPL, + + // 68000 CPU memory interface: + input [15:0] cpuDataIn, + input [3:0] cpuAddrRegHi, // A12-A9 + input [2:0] cpuAddrRegMid, // A6-A4 + input [1:0] cpuAddrRegLo, // A2-A1 + input _cpuUDS, + input _cpuLDS, + input _cpuRW, + output reg [15:0] cpuDataOut, + + // peripherals: + input selectSCSI, + input selectSCC, + input selectIWM, + input selectVIA, + + // RAM/ROM: + input cpuBusControl, + input [15:0] memoryDataIn, + output [15:0] memoryDataOut, + + // keyboard: + input [64:0] ps2_key, + output capslock, + + // mouse: + input [24:0] ps2_mouse, + + // serial: + input serialIn, + output serialOut, + + // video: + input _hblank, + input _vblank, + + // audio + output [10:0] audioOut, // 8 bit audio + 3 bit volume + output snd_alt, + input loadSound, + + // misc + output memoryOverlayOn, + input [1:0] insertDisk, + input [1:0] diskSides, + output [1:0] diskEject, + + output [1:0] diskMotor, + output [1:0] diskAct, + + output [21:0] dskReadAddrInt, + input dskReadAckInt, + output [21:0] dskReadAddrExt, + input dskReadAckExt, + + // connections to io controller + output [31:0] io_lba, + output io_rd, + output io_wr, + input io_ack, + + input [8:0] sd_buff_addr, + input [7:0] sd_buff_dout, + output [7:0] sd_buff_din, + input sd_buff_wr +); + +// add binary volume levels according to volume setting +assign audioOut = + (snd_vol[0] ? audio_latch : 11'd0) + + (snd_vol[1] ? audio_latch<<1 : 11'd0) + + (snd_vol[2] ? audio_latch<<2 : 11'd0); + +reg [10:0] audio_latch; +always @(posedge clk) begin + reg loadSoundD; + if(cen) loadSoundD <= loadSound; + if(cep && loadSoundD) begin + if(snd_ena) audio_latch <= 0; + else audio_latch <= memoryDataIn[15:8]; + end +end + +// CPU reset generation +// For initial CPU reset, RESET and HALT must be asserted for at least 100ms = 800,000 clocks of clk8 +reg [19:0] resetDelay; // 20 bits = 1 million +wire isResetting = resetDelay != 0; + +initial begin + // force a reset when the FPGA configuration is completed + resetDelay <= 20'hFFFFF; +end + +always @(posedge clk or negedge _systemReset) begin + if (_systemReset == 1'b0) begin + resetDelay <= 20'hFFFFF; + end + else if(cep && isResetting) begin + resetDelay <= resetDelay - 1'b1; + end +end +assign _cpuReset = isResetting ? 1'b0 : 1'b1; + +// interconnects +wire SEL; +wire _viaIrq, _sccIrq, sccWReq; +wire [15:0] viaDataOut; +wire [15:0] iwmDataOut; +wire [7:0] sccDataOut; +wire [7:0] scsiDataOut; +wire mouseX1, mouseX2, mouseY1, mouseY2, mouseButton; + +// interrupt control +assign _cpuIPL = + !_viaIrq?3'b110: + !_sccIrq?3'b101: + 3'b111; + +// Serial port +assign serialOut = 0; + +// CPU-side data output mux +always @(*) begin + casex({selectIWM, selectVIA, selectSCC, selectSCSI}) + 'b1xxx: cpuDataOut = iwmDataOut; + 'b01xx: cpuDataOut = viaDataOut; + 'b001x: cpuDataOut = { sccDataOut, 8'hEF }; + 'b0001: cpuDataOut = { scsiDataOut, 8'hEF }; + 'b0000: cpuDataOut = memoryDataIn; + endcase +end + +// Memory-side +assign memoryDataOut = cpuDataIn; + +// SCSI +ncr5380 scsi +( + .clk(clk), + .ce(cep), + + .reset(!_cpuReset), + .bus_cs(selectSCSI && cpuBusControl), + .bus_we(!_cpuRW), + .bus_rs(cpuAddrRegMid), + .dack(cpuAddrRegHi[0]), // A9 + .wdata(cpuDataIn[15:8]), + .rdata(scsiDataOut), + + // connections to io controller + .io_lba ( io_lba ), + .io_rd ( io_rd ), + .io_wr ( io_wr ), + .io_ack ( io_ack ), + + .sd_buff_addr(sd_buff_addr), + .sd_buff_dout(sd_buff_dout), + .sd_buff_din(sd_buff_din), + .sd_buff_wr(sd_buff_wr) +); + + +// VIA +wire [2:0] snd_vol; +wire snd_ena; + +via v +( + .clk(clk), + .cep(cep), + .cen(cen), + + ._reset(_cpuReset), + .selectVIA(selectVIA && cpuBusControl), + ._cpuRW(_cpuRW), + ._cpuUDS(_cpuUDS), + .dataIn(cpuDataIn), + .cpuAddrRegHi(cpuAddrRegHi), + ._hblank(_hblank), + ._vblank(_vblank), + .mouseY2(mouseY2), + .mouseX2(mouseX2), + .mouseButton(mouseButton), + .sccWReq(sccWReq), + ._irq(_viaIrq), + .dataOut(viaDataOut), + .memoryOverlayOn(memoryOverlayOn), + .SEL(SEL), + + .snd_vol(snd_vol), + .snd_ena(snd_ena), + .snd_alt(snd_alt), + + .kbd_in_data(kbd_in_data), + .kbd_in_strobe(kbd_in_strobe), + .kbd_out_data(kbd_out_data), + .kbd_out_strobe(kbd_out_strobe) +); + +// IWM +iwm i +( + .clk(clk), + .cep(cep), + .cen(cen), + + ._reset(_cpuReset), + .selectIWM(selectIWM && cpuBusControl), + ._cpuRW(_cpuRW), + ._cpuLDS(_cpuLDS), + .dataIn(cpuDataIn), + .cpuAddrRegHi(cpuAddrRegHi), + .SEL(SEL), + .dataOut(iwmDataOut), + .insertDisk(insertDisk), + .diskSides(diskSides), + .diskEject(diskEject), + .diskMotor(diskMotor), + .diskAct(diskAct), + + .dskReadAddrInt(dskReadAddrInt), + .dskReadAckInt(dskReadAckInt), + .dskReadAddrExt(dskReadAddrExt), + .dskReadAckExt(dskReadAckExt), + .dskReadData(memoryDataIn[7:0]) +); + +// SCC +scc s +( + .clk(clk), + .cep(cep), + .cen(cen), + + .reset_hw(~_cpuReset), + .cs(selectSCC && (_cpuLDS == 1'b0 || _cpuUDS == 1'b0) && cpuBusControl), + .we(!_cpuRW), + .rs(cpuAddrRegLo), + .wdata(cpuDataIn[15:8]), + .rdata(sccDataOut), + ._irq(_sccIrq), + .dcd_a(mouseX1), + .dcd_b(mouseY1), + .wreq(sccWReq) +); + +// Mouse +ps2_mouse mouse +( + .reset(~_cpuReset), + + .clk(clk), + .ce(cep), + + .ps2_mouse(ps2_mouse), + + .x1(mouseX1), + .y1(mouseY1), + .x2(mouseX2), + .y2(mouseY2), + .button(mouseButton) +); + +wire [7:0] kbd_in_data; +wire kbd_in_strobe; +wire [7:0] kbd_out_data; +wire kbd_out_strobe; + +// Keyboard +ps2_kbd kbd +( + .reset(~_cpuReset), + + .clk(clk), + .ce(cep), + + .ps2_key(ps2_key), + .capslock(capslock), + + .data_out(kbd_out_data), // data from mac + .strobe_out(kbd_out_strobe), + .data_in(kbd_in_data), // data to mac + .strobe_in(kbd_in_strobe) +); + +endmodule diff --git a/floppy.v b/floppy.v new file mode 100644 index 0000000..1e12c85 --- /dev/null +++ b/floppy.v @@ -0,0 +1,340 @@ +/* Synchronous 8-bit replica of 3.5 inch floppy disk drive. + + Differences from the true floppy interace at the Mac's DB-19 port: + True interface has a writeReq control line, only 1-bit readData and writeData, and no clk. + True interface does not have newByteReady signal. Instead the IWM must watch the data in bit and synchronize with it to + determine the timing and framing of bytes. + +*/ + +/* Disk register (read): + State-control lines Register + CA2 CA1 CA0 SEL addressed Information in register + + 0 0 0 0 DIRTN Head step direction (0=toward track 79, 1=toward track 0) + 0 0 0 1 CSTIN Disk in place (0=disk is inserted) + 0 0 1 0 STEP Drive head stepping (setting to 0 performs a step, returns to 1 when step is complete) + 0 0 1 1 WRTPRT Disk locked (0=locked) + 0 1 0 0 MOTORON Drive motor running (0=on, 1=off) + 0 1 0 1 TKO Head at track 0 (0=at track 0) + 0 1 1 0 SWITCHED Disk switched (1=yes?) + 0 1 1 1 TACH Tachometer (produces 60 pulses for each rotation of the drive motor) + 1 0 0 0 RDDATA0 Read data, lower head, side 0 + 1 0 0 1 RDDATA1 Read data, upper head, side 1 + 1 0 1 0 SUPERDR Drive is a Superdrive (0=no, 1=yes) + 1 1 0 0 SIDES Single- or double-sided drive (0=single side, 1=double side) + 1 1 0 1 READY 0 = yes + 1 1 1 0 INSTALLED 0 = yes + 1 1 1 1 DRVIN 400K/800K: Drive installed (0=drive is present), Superdrive: Inserted disk capacity (0=HD, 1=DD) + + Disk registers (write): + Control lines Register + CA1 CA0 SEL addressed Register function + + 0 0 0 DIRTN Set stepping direction (0=toward track 79, 1=toward track 0) + 0 0 1 SWITCHED Reset disk switched flag (writing 1 sets switch flag to 0) + 0 1 0 STEP Step the drive head one track (setting to 0 performs a step, returns to 1 when step is complete) + 1 0 0 MOTORON Turn on/off drive motor (0=on, 1=off) + 1 1 0 EJECT Eject the disk (writing 1 ejects the disk) + +*/ + +`define DRIVE_REG_DIRTN 0 /* R/W: step direction (0=toward track 79, 1=toward track 0) */ +`define DRIVE_REG_CSTIN 1 /* R: disk in place (1 = no disk) */ + /* W: ?? reset disk switch flag ? */ +`define DRIVE_REG_STEP 2 /* R: drive head is stepping (1 = complete) */ + /* W: 0 = step drive head */ +`define DRIVE_REG_WRTPRT 3 /* R: 0 = disk is write-protected */ +`define DRIVE_REG_MOTORON 4 /* R/W: 0 = motor on */ +`define DRIVE_REG_TK0 5 /* R: 0 = head at track 0 */ +`define DRIVE_REG_EJECT 6 /* R: disk switched (1=yes?)*/ + /* W: 1 = eject the disk */ +`define DRIVE_REG_TACH 7 /* R: tach-o-meter */ +`define DRIVE_REG_RDDATA0 8 /* R: activate lower head: side 0 */ +`define DRIVE_REG_RDDATA1 9 /* R: activate upper head: side 1 */ +`define DRIVE_REG_SUPERDR 10 /* R: drive is a superdrive (0=no, 1=yes) */ +`define DRIVE_REG_SIDES 12 /* R: number of sides (0=single, 1=dbl) */ +`define DRIVE_REG_READY 13 /* R: drive ready (head loaded) (0=ready) */ +`define DRIVE_REG_INSTALLED 14 /* R: drive present (0 = yes ??) */ +`define DRIVE_REG_DRVIN 15 /* R: 400K/800k: drive present (0=yes, 1=no), Superdrive: disk capacity (0=HD, 1=DD) */ + +module floppy +( + input clk, + input cep, + input cen, + + input _reset, + input ca0, // PH0 + input ca1, // PH1 + input ca2, // PH2 + input SEL, // HDSEL from VIA + input lstrb, // aka PH3 + input _enable, + input [7:0] writeData, + output [7:0] readData, + + input advanceDriveHead, // prevents overrun when debugging, does not exist on a real Mac! + output reg newByteReady, + input insertDisk, + input diskSides, + output diskEject, + + output motor, + output act, + + output [21:0] dskReadAddr, + input dskReadAck, + input [7:0] dskReadData +); + + assign motor = ~driveRegs[`DRIVE_REG_MOTORON]; + assign act = lstrbEdge; + + reg [15:0] driveRegs; + reg [6:0] driveTrack; + reg driveSide; + reg [7:0] diskDataIn; // incoming byte from the floppy disk + + // read drive registers + wire [15:0] driveRegsAsRead = { + 1'b0, // DRVIN = yes + 1'b0, // INSTALLED = yes + 1'b0, // READY = yes + 1'b1, // SIDES = double-sided drive + 1'b0, // UNUSED + 1'b0, // SUPERDR + 1'b0, // RDDATA1 + 1'b0, // RDDATA0 + driveRegs[`DRIVE_REG_TACH], // TACH: 60 pules for each rotation of the drive motor + 1'b0, // disk switched? + ~(driveTrack == 7'h00), // TK0: track 0 indicator + driveRegs[`DRIVE_REG_MOTORON], // motor on + 1'b0, // WRTPRT = locked + 1'b1, // STEP = complete + driveRegs[`DRIVE_REG_CSTIN], // disk in drive + driveRegs[`DRIVE_REG_DIRTN] // step direction + }; + + reg dskReadAckD; + always @(posedge clk) if(cen) dskReadAckD <= dskReadAck; + + // latch incoming data + reg [7:0] dskReadDataLatch; + always @(posedge clk) if(cep && dskReadAckD) dskReadDataLatch <= dskReadData; + + wire [7:0] dskReadDataEnc; + + reg old_newByteReady; + always @(posedge clk) old_newByteReady <= newByteReady; + + // include track encoder + floppy_track_encoder enc + ( + + .clk ( clk ), + .ready ( ~old_newByteReady & newByteReady ), + + .rst ( !_reset ), + + .side ( driveSide ), + .sides ( doubleSidedDisk ), + .track ( driveTrack ), + + .addr ( dskReadAddr ), + .idata ( dskReadDataLatch ), + .odata ( dskReadDataEnc ) + ); + + // TODO: auto-detect doubleSidedDisk from image file size + wire doubleSidedDisk = diskSides; + + wire [3:0] driveReadAddr = {ca2,ca1,ca0,SEL}; + + // a byte is read or written every 128 clocks (2 us per bit * 8 bits = 16 us, @ 8 MHz = 128 clocks) + // The CPU must poll for data at least this often, or else an overrun will occur. + reg [6:0] diskDataByteTimer; + reg [7:0] diskImageData; + reg readyToAdvanceHead; + always @(posedge clk or negedge _reset) begin + if (_reset == 0) begin + driveSide <= 0; + diskImageData <= 8'h00; + diskDataIn <= 8'hFF; + diskDataByteTimer <= 0; + readyToAdvanceHead <= 1; + newByteReady <= 1'b0; + end + else begin + if(cep) begin + // at time 0, latch a new byte and advance the drive head + if (diskDataByteTimer == 0 && readyToAdvanceHead && diskImageData != 0) begin + diskDataIn <= diskImageData; + newByteReady <= 1; + diskDataByteTimer <= 1; // make timer run again + + // clear diskImageData after it's used, so we can tell when we get a new one from the disk + diskImageData <= 0; + + // for debugging, don't advance the head until the IWM says it's ready + readyToAdvanceHead <= 1'b1; // TEMP: treat IWM as always ready + end + + // extraRomReadAck comes every hsync which is every 21us. The iwm data rates + // is 8MHZ/128 = 16us + else begin + // a timer governs when the next disk byte will become available + diskDataByteTimer <= diskDataByteTimer + 1'b1; + + newByteReady <= 1'b0; + + if (dskReadAck) begin + // whenever ACK is received, store the data from the current diskImageAddr + diskImageData <= dskReadDataEnc; // xyz + end + + if (advanceDriveHead) begin + readyToAdvanceHead <= 1'b1; + end + end + + // switch drive sides if DRIVE_REG_RDDATA0 or DRIVE_REG_RDDATA1 are read + // TODO: we don't know if this is a true read, since we don't know if IWM is selected or + // could be bad if we use this test to flush a cache of encoded disk data + if (driveReadAddr == `DRIVE_REG_RDDATA0 && lstrb == 1'b0) + driveSide <= 0; + if (driveReadAddr == `DRIVE_REG_RDDATA1 && lstrb == 1'b0) + driveSide <= 1; + end + end + end + + // create a signal on the falling edge of lstrb + reg lstrbPrev; + always @(posedge clk) if(cep) lstrbPrev <= lstrb; + + wire lstrbEdge = lstrb == 1'b0 && lstrbPrev == 1'b1; + + assign readData = (driveReadAddr == `DRIVE_REG_RDDATA0 || driveReadAddr == `DRIVE_REG_RDDATA1) ? diskDataIn : + { driveRegsAsRead[driveReadAddr], 7'h00 }; + + // write drive registers + wire [2:0] driveWriteAddr = {ca1,ca0,SEL}; + + // DRIVE_REG_DIRTN 0 /* R/W: step direction (0=toward track 79, 1=toward track 0) */ + always @(posedge clk or negedge _reset) begin + if (_reset == 1'b0) begin + driveRegs[`DRIVE_REG_DIRTN] <= 1'b0; + end + else if(cep && _enable == 1'b0 && lstrbEdge == 1'b1 && driveWriteAddr == `DRIVE_REG_DIRTN) begin + driveRegs[`DRIVE_REG_DIRTN] <= ca2; + end + end + + + // DRIVE_REG_CSTIN 1 /* R: disk in place (1 = no disk) */ + /* W: ?? reset disk switch flag ? */ + // disk in drive indicators + reg [23:0] ejectIndicatorTimer; + assign diskEject = (ejectIndicatorTimer != 0); + + always @(posedge clk or negedge _reset) begin + if (_reset == 1'b0) begin + driveRegs[`DRIVE_REG_CSTIN] <= 1'b1; + ejectIndicatorTimer <= 24'd0; + end + else if(cep) begin + if (_enable == 1'b0 && lstrbEdge == 1'b1 && driveWriteAddr == `DRIVE_REG_EJECT && ca2 == 1'b1) begin + // eject the disk + driveRegs[`DRIVE_REG_CSTIN] <= 1'b1; + ejectIndicatorTimer <= 24'hFFFFFF; + end + else if (insertDisk) begin + // insert a disk + driveRegs[`DRIVE_REG_CSTIN] <= 1'b0; + end + else begin + if (ejectIndicatorTimer != 0) + ejectIndicatorTimer <= ejectIndicatorTimer - 1'b1; + end + end + end + + //`define DRIVE_REG_STEP 2 /* R: drive head stepping (1 = complete) */ + /* W: 0 = step drive head */ + always @(posedge clk or negedge _reset) begin + if (_reset == 1'b0) begin + driveTrack <= 0; + end + else if(cep && _enable == 1'b0 && lstrbEdge == 1'b1 && driveWriteAddr == `DRIVE_REG_STEP && ca2 == 1'b0) begin + if (driveRegs[`DRIVE_REG_DIRTN] == 1'b0 && driveTrack != 7'h4F) begin + driveTrack <= driveTrack + 1'b1; + end + if (driveRegs[`DRIVE_REG_DIRTN] == 1'b1 && driveTrack != 0) begin + driveTrack <= driveTrack - 1'b1; + end + end + end + + // DRIVE_REG_MOTORON 4 /* R/W: 0 = motor on */ + always @(posedge clk or negedge _reset) begin + if (_reset == 1'b0) begin + driveRegs[`DRIVE_REG_MOTORON] <= 1'b1; + end + else if (cep && _enable == 1'b0 && lstrbEdge == 1'b1 && driveWriteAddr == `DRIVE_REG_MOTORON) begin + driveRegs[`DRIVE_REG_MOTORON] <= ca2; + end + end + + // DRIVE_REG_TACH 7 Tachometer (produces 60 pulses for each rotation of the drive motor) + /* Data from MESS, sonydriv.c: + Tracks RPM Timing Value + 00-15: 500 timing value $117B (acceptable range {1135-11E9}) + 16-31: 550 timing value $???? (acceptable range {12C6-138A}) + 32-47: 600 timing value $???? (acceptable range {14A7-157F}) + 48-63: 675 timing value $???? (acceptable range {16F2-17E2}) + 64-79: 750 timing value $???? (acceptable range {19D0-1ADE}) + + Experimentally determined toggle rates for Plus Too with 8.125 MHz CPU clock: + TACH Half Period Clocks Resulting Timing Value + 9996 $117B (4475) + 9122 $1328 (4904) + 8292 $1513 (5395) + 7463 $176A (5994) + 6634 $1A56 (6742) + */ + + reg [13:0] driveTachTimer; + reg [13:0] driveTachPeriod; + + always @(*) begin + case (driveTrack[6:4]) + 0: // tracks 0-15 + driveTachPeriod <= 9996; + 1: // tracks 16-31 + driveTachPeriod <= 9122; + 2: // tracks 32-47 + driveTachPeriod <= 8292; + 3: // tracks 48-63 + driveTachPeriod <= 7463; + default: // tracks 64-79 + driveTachPeriod <= 6634; + endcase + end + + always @(posedge clk or negedge _reset) begin + if (_reset == 1'b0) begin + driveRegs[`DRIVE_REG_TACH] <= 1'b0; + driveTachTimer <= 0; + end + else if(cep) begin + if (driveTachTimer == driveTachPeriod) begin + driveTachTimer <= 0; + driveRegs[`DRIVE_REG_TACH] <= ~driveRegs[`DRIVE_REG_TACH]; + end + else begin + driveTachTimer <= driveTachTimer + 1'b1; + end + end + end +endmodule diff --git a/floppy_track_encoder.v b/floppy_track_encoder.v new file mode 100644 index 0000000..5fd48be --- /dev/null +++ b/floppy_track_encoder.v @@ -0,0 +1,367 @@ +/* + floppy_track_encoder.v + + encode a full floppy track from raw sector data on the fly + + */ + +/* verilator lint_off UNUSED */ +/* verilator lint_off UNDRIVEN */ +/* verilator lint_off CASEINCOMPLETE */ + +module floppy_track_encoder ( + // system signals + input clk, // clock at which data bytes are delivered via odata + input ready, + input rst, + + input side, + input sides, + input [6:0] track, // current track + + output [21:0] addr, // address to fetch from + input [7:0] idata, + + output [7:0] odata +); + +assign addr = + { 3'b00, soff, 9'd0 } + // sector offset * 512 for two sides + (sides?{ 3'b00, soff, 9'd0 }:22'd0) + // another sector offset * 512 for two sides + (side?{ 9'd0, spt, 9'd0 }:22'd0) + // side * sectors * 512 + { 9'd0, sector, src_offset }; // offset within track + + // number of sectors on current track + wire [3:0] spt = + (track[6:4] == 3'd0)?4'd12: // track 0 - 15 + (track[6:4] == 3'd1)?4'd11: // track 16 - 31 + (track[6:4] == 3'd2)?4'd10: // track 32 - 47 + (track[6:4] == 3'd3)?4'd9: // track 48 - 63 + 4'd8; // track 64 - ... + + // all possible tack*sector factors + wire [9:0] track_times_12 = // x*12 = x*8 + x*4 + { track, 3'b000 } + // x<<3 + + { 1'b0, track, 2'b00 }; // x<<2 + + wire [9:0] track_times_11 = // x*11 = x*8 + x*2 + x*1 + { track, 3'b000 } + // x<<3 + + { 2'b00, track, 1'b0 } + // x<<1 + + { 3'b000, track }; // x<<0 + + wire [9:0] track_times_10 = // x*10 = x*8 + x*2 + { track, 3'b000 } + // x<<3 + + { 2'b00, track, 1'b0 }; // x<<1 + + wire [9:0] track_times_9 = // x*9 = x*8 + x*1 + { track, 3'b000 } + // x<<3 + + { 3'b000, track }; // x<<0 + + wire [9:0] track_times_8 = // x*8 + { track, 3'b000 }; // x<<3 + + // sector offset of current track is the sum of all sectors on all tracks before + wire [6:0] trackm1 = track - 7'd1; + wire [9:0] soff = + (track == 0)?10'd0: // track 0 + (trackm1[6:4] == 3'd0)?track_times_12: // track 1 - 16 + (trackm1[6:4] == 3'd1)?(track_times_11 + 10'd16): // track 17 - 32 + (trackm1[6:4] == 3'd2)?(track_times_10 + 10'd32 + 10'd16): // track 33 - 48 + (trackm1[6:4] == 3'd3)?(track_times_9 + 10'd48 + 10'd32 + 10'd16): // track 49 - 64 + (track_times_8 + 10'd64 + 10'd48 + 10'd32 + 10'd16); // track 65 - + + // parts of an address block + wire [5:0] sec_in_tr = {2'b00, sector}; + wire [5:0] track_low = track[5:0]; + wire [5:0] track_hi = { side, 4'b0000, track[6] }; + wire [5:0] format = { sides, 5'h2 }; // double sided = 22, single sided = 2 + wire [5:0] checksum = track_low ^ sec_in_tr ^ track_hi ^ format; + + // data input to the sony encoder during address block + wire [5:0] sony_addr_in = + (count == 3)?track_low: + (count == 4)?sec_in_tr: + (count == 5)?track_hi: + (count == 6)?format: + checksum; + + // data input to the sony encoder during data header + wire [5:0] sony_dhdr_in = sec_in_tr; + + wire [5:0] sony_dsum_in = + (count == 0)?{ c3[7:6], c2[7:6], c1[7:6] }: + (count == 1)?c3[5:0]: + (count == 2)?c2[5:0]: + c1[5:0]; + + // feed data into sony encoder + wire [5:0] si = + (state == STATE_ADDR)?sony_addr_in: + (state == STATE_DHDR)?sony_dhdr_in: + (state == STATE_DZRO)?nib_out: + (state == STATE_DPRE)?nib_out: + (state == STATE_DATA)?nib_out: + (state == STATE_DSUM)?sony_dsum_in: + 6'h3f; + + // encoder table taken from MESS emulator + wire [7:0] sony_to_disk_byte = + (si==6'h00)?8'h96:(si==6'h01)?8'h97:(si==6'h02)?8'h9a:(si==6'h03)?8'h9b: // 0x00 + (si==6'h04)?8'h9d:(si==6'h05)?8'h9e:(si==6'h06)?8'h9f:(si==6'h07)?8'ha6: + (si==6'h08)?8'ha7:(si==6'h09)?8'hab:(si==6'h0a)?8'hac:(si==6'h0b)?8'had: + (si==6'h0c)?8'hae:(si==6'h0d)?8'haf:(si==6'h0e)?8'hb2:(si==6'h0f)?8'hb3: + + (si==6'h10)?8'hb4:(si==6'h11)?8'hb5:(si==6'h12)?8'hb6:(si==6'h13)?8'hb7: // 0x10 + (si==6'h14)?8'hb9:(si==6'h15)?8'hba:(si==6'h16)?8'hbb:(si==6'h17)?8'hbc: + (si==6'h18)?8'hbd:(si==6'h19)?8'hbe:(si==6'h1a)?8'hbf:(si==6'h1b)?8'hcb: + (si==6'h1c)?8'hcd:(si==6'h1d)?8'hce:(si==6'h1e)?8'hcf:(si==6'h1f)?8'hd3: + + (si==6'h20)?8'hd6:(si==6'h21)?8'hd7:(si==6'h22)?8'hd9:(si==6'h23)?8'hda: // 0x20 + (si==6'h24)?8'hdb:(si==6'h25)?8'hdc:(si==6'h26)?8'hdd:(si==6'h27)?8'hde: + (si==6'h28)?8'hdf:(si==6'h29)?8'he5:(si==6'h2a)?8'he6:(si==6'h2b)?8'he7: + (si==6'h2c)?8'he9:(si==6'h2d)?8'hea:(si==6'h2e)?8'heb:(si==6'h2f)?8'hec: + + (si==6'h30)?8'hed:(si==6'h31)?8'hee:(si==6'h32)?8'hef:(si==6'h33)?8'hf2: // 0x30 + (si==6'h34)?8'hf3:(si==6'h35)?8'hf4:(si==6'h36)?8'hf5:(si==6'h37)?8'hf6: + (si==6'h38)?8'hf7:(si==6'h39)?8'hf9:(si==6'h3a)?8'hfa:(si==6'h3b)?8'hfb: + (si==6'h3c)?8'hfc:(si==6'h3d)?8'hfd:(si==6'h3e)?8'hfe: 8'hff; + + // states of encoder state machine + localparam STATE_SYN0 = 4'd0; // 56 bytes sync pattern (0xff) + localparam STATE_ADDR = 4'd1; // 10 bytes address block + localparam STATE_SYN1 = 4'd2; // 5 bytes sync pattern (0xff) + localparam STATE_DHDR = 4'd3; // 4 bytes data block header + localparam STATE_DZRO = 4'd4; // 8 encoded zero bytes in data block + localparam STATE_DPRE = 4'd5; // 4 bytes data prefetch + localparam STATE_DATA = 4'd6; // the payload itself + localparam STATE_DSUM = 4'd7; // 4 bytes data checksum + localparam STATE_DTRL = 4'd8; // 3 bytes data block trailer + localparam STATE_WAIT = 4'd15; // wait until start of next sector + + // output data during address block + wire [7:0] odata_addr = + (count == 0)?8'hd5: + (count == 1)?8'haa: + (count == 2)?8'h96: + (count == 8)?8'hde: + (count == 9)?8'haa: + sony_to_disk_byte; + + wire [7:0] odata_dhdr = + (count == 0)?8'hd5: + (count == 1)?8'haa: + (count == 2)?8'had: + sony_to_disk_byte; + + wire [7:0] odata_dtrl = + (count == 0)?8'hde: + (count == 1)?8'haa: + 8'hff; + + // demultiplex output data + assign odata = (state == STATE_ADDR)?odata_addr: + (state == STATE_DHDR)?odata_dhdr: + (state == STATE_DZRO)?sony_to_disk_byte: + (state == STATE_DPRE)?sony_to_disk_byte: + (state == STATE_DATA)?sony_to_disk_byte: + (state == STATE_DSUM)?sony_to_disk_byte: + (state == STATE_DTRL)?odata_dtrl: + 8'hff; + + // ------------------------ nibbler ---------------------------- + + reg [7:0] c1; + reg [7:0] c2; + reg c2x; + reg [7:0] c3; + reg c3x; + + wire nibbler_reset = (state == STATE_DHDR); + reg [1:0] cnt; + + reg [7:0] nib_xor_0; + reg [7:0] nib_xor_1; + reg [7:0] nib_xor_2; + + // request an input byte. this happens 4 byte ahead of output. + // only three bytes are read while four bytes are written due + // to 6:2 encoding + wire strobe = ((state == STATE_DPRE) || + ((state == STATE_DATA) && (count < 683-4-1))) + && (cnt != 3); + +reg [7:0] data_latch; +always @(posedge clk) if(ready && strobe) data_latch <= idata; + +always @(posedge clk or posedge nibbler_reset) begin + if(nibbler_reset) begin + c1 <= 8'h00; + c2 <= 8'h00; + c2x <= 1'b0; + c3 <= 8'h00; + c3x <= 1'b0; + cnt <= 2'd0; + nib_xor_0 <= 8'h00; + nib_xor_1 <= 8'h00; + nib_xor_2 <= 8'h00; + end else if(ready && ((state == STATE_DPRE) || (state == STATE_DATA))) begin + cnt <= cnt + 2'd1; + + // memory read during cnt 0-3 + if(count < 683-4) begin + + // encode first byte + if(cnt == 1) begin + c1 <= { c1[6:0], c1[7] }; + { c3x, c3 } <= { 1'b0, c3 } + { 1'b0, nib_in } + { 8'd0, c1[7] }; + nib_xor_0 <= nib_in ^ { c1[6:0], c1[7] }; + end + + // encode second byte + if(cnt == 2) begin + { c2x, c2 } <= { 1'b0, c2 } + { 1'b0, nib_in } + { 8'd0, c3x }; + c3x <= 1'b0; + nib_xor_1 <= nib_in ^ c3; + end + + // encode third byte + if(cnt == 3) begin + c1 <= c1 + nib_in + { 7'd0, c2x }; + c2x <= 1'b0; + nib_xor_2 <= nib_in ^ c2; + end + end else begin + // since there are 512/3 = 170 2/3 three byte blocks in a sector the + // last run has to be filled up with zeros + if(cnt == 3) + nib_xor_2 <= 8'h00; + end + end +end + +// bytes going into the nibbler +wire [7:0] nib_in = + (state == STATE_DZRO)?8'h00: + data_latch; + +// four six bit units come out of the nibbler +wire [5:0] nib_out = + (cnt == 1)?nib_xor_0[5:0]: + (cnt == 2)?nib_xor_1[5:0]: + (cnt == 3)?nib_xor_2[5:0]: + { nib_xor_0[7:6], nib_xor_1[7:6], nib_xor_2[7:6] }; + +// count bytes per sector +reg [3:0] state; +reg [9:0] count; +reg [3:0] sector; +reg [8:0] src_offset; +always @(posedge clk or posedge rst) begin + if(rst) begin + count <= 10'd0; + state <= STATE_SYN0; + sector <= 4'd0; + src_offset <= 9'd0; + end else if(ready) begin + count <= count + 10'd1; + + if(strobe) + src_offset <= src_offset + 9'd1; + + case(state) + + // send 14*4=56 sync bytes + STATE_SYN0: begin + if(count == 55) begin + state <= STATE_ADDR; + count <= 10'd0; + end + end + + // send 10 bytes address block + STATE_ADDR: begin + if(count == 9) begin + state <= STATE_SYN1; + count <= 10'd0; + end + end + + // send 5 sync bytes + STATE_SYN1: begin + if(count == 4) begin + state <= STATE_DHDR; + count <= 10'd0; + end + end + + // send 4 bytes data block hdr + STATE_DHDR: begin + if(count == 3) begin + state <= STATE_DZRO; + count <= 10'd0; + end + end + + // send 8 zero bytes before data block + STATE_DZRO: begin + if(count == 11) begin + state <= STATE_DPRE; + count <= 10'd0; + end + end + + // start prefetching 4 bytes data + STATE_DPRE: begin + if(count == 3) begin + state <= STATE_DATA; + count <= 10'd0; + end + end + + // send 512 bytes data block 6:2 encoded in 683 bytes + STATE_DATA: begin + if(count == 682) begin + state <= STATE_DSUM; + count <= 10'd0; + end + end + + // send 4 bytes data checksum + STATE_DSUM: begin + if(count == 3) begin + state <= STATE_DTRL; + count <= 10'd0; + end + end + + // send 3 bytes data block trailer + STATE_DTRL: begin + if(count == 2) begin + state <= STATE_WAIT; + count <= 10'd0; + end + end + + // fill sector up to 1024 bytes + STATE_WAIT: begin +// if(count == 1023-56-10-5-4-12-4-683-4-3) + begin + count <= 10'd0; + state <= STATE_SYN0; + src_offset <= 9'd0; + + // interleave of 1 +// if(sector != spt-4'd1) sector <= sector + 4'd1; +// else sector <= 4'd0; + + // interleave of 2 + if((sector == spt-4'd2) || + (sector == spt-4'd1)) sector <= { 3'd0, !sector[0] }; + else sector <= sector + 4'd2; + end + end + endcase + end +end + +endmodule diff --git a/iwm.v b/iwm.v new file mode 100644 index 0000000..d2594d8 --- /dev/null +++ b/iwm.v @@ -0,0 +1,308 @@ +/* IWM + + Mapped to $DFE1FF - $DFFFFF + + The 16 IWM one-bit registers are {8'hDF, 8'b111xxxx1, 8'hFF}: + 0 $0 ca0L CA0 off (0) + 1 $200 ca0H CA0 on (1) + 2 $400 ca1L CA1 off (0) + 3 $600 ca1H CA1 on (1) + 4 $800 ca2L CA2 off (0) + 5 $A00 ca2H CA2 on (1) + 6 $C00 ph3L LSTRB off (low) + 7 $E00 ph3H LSTRB on (high) + 8 $1000 mtrOff ENABLE disk enable off + 9 $1200 mtrOn ENABLE disk enable on + 10 $1400 intDrive SELECT select internal drive + 11 $1600 extDrive SELECT select external drive + 12 $1800 q6L Q6 off + 13 $1A00 q6H Q6 on + 14 $1C00 q7L Q7 off, read register + 15 $1E00 q7H Q7 on, write register + + Notes from IWM manual: + Serial data is shifted in/out MSB first, with a bit transferred every 2 microseconds. + When writing data, a 1 is written as a transition on writeData at a bit cell boundary time, and a 0 is written as no transition. + When reading data, a falling transition within a bit cell window is considered to be a 1, and no falling transition is considered a 0. + When reading data, the read data register will latch the shift register when a 1 is shifted into the MSB. + The read data register will be cleared 14 fclk periods (about 2 microseconds) after a valid data read takes place-- a valid data read + being defined as both /DEV being low and D7 (the MSB) outputting a one from the read data register for at least one fclk period. +*/ + +module iwm +( + input clk, + input cep, + input cen, + + input clk8, + + input _reset, + input selectIWM, + input _cpuRW, + input _cpuLDS, + input [15:0] dataIn, + input [3:0] cpuAddrRegHi, + input SEL, // from VIA + output [15:0] dataOut, + input [1:0] insertDisk, + output [1:0] diskEject, + input [1:0] diskSides, + + output [1:0] diskMotor, + output [1:0] diskAct, + + // interface to fetch data for internal drive + output [21:0] dskReadAddrInt, + input dskReadAckInt, + output [21:0] dskReadAddrExt, + input dskReadAckExt, + input [7:0] dskReadData +); + + wire [7:0] dataInLo = dataIn[7:0]; + reg [7:0] dataOutLo; + assign dataOut = { 8'hBE, dataOutLo }; + + // IWM state + reg ca0, ca1, ca2, lstrb, selectExternalDrive, q6, q7; + reg ca0Next, ca1Next, ca2Next, lstrbNext, selectExternalDriveNext, q6Next, q7Next; + wire advanceDriveHead; // prevents overrun when debugging, does not exit on a real Mac! + reg [7:0] writeData; + reg [7:0] readDataLatch; + wire _iwmBusy, _writeUnderrun; + assign _iwmBusy = 1'b1; // for writes, a value of 1 here indicates the IWM write buffer is empty + assign _writeUnderrun = 1'b1; + + // floppy disk drives + reg diskEnableExt, diskEnableInt; + reg diskEnableExtNext, diskEnableIntNext; + wire newByteReadyInt; + wire [7:0] readDataInt; + wire senseInt = readDataInt[7]; // bit 7 doubles as the sense line here + wire newByteReadyExt; + wire [7:0] readDataExt; + wire senseExt = readDataExt[7]; // bit 7 doubles as the sense line here + + floppy floppyInt + ( + .clk(clk), + .cep(cep), + .cen(cen), + + ._reset(_reset), + .ca0(ca0), + .ca1(ca1), + .ca2(ca2), + .SEL(SEL), + .lstrb(lstrb), + ._enable(~diskEnableInt), + .writeData(writeData), + .readData(readDataInt), + .advanceDriveHead(advanceDriveHead), + .newByteReady(newByteReadyInt), + .insertDisk(insertDisk[0]), + .diskSides(diskSides[0]), + .diskEject(diskEject[0]), + + .motor(diskMotor[0]), + .act(diskAct[0]), + + .dskReadAddr(dskReadAddrInt), + .dskReadAck(dskReadAckInt), + .dskReadData(dskReadData) + ); + + floppy floppyExt + ( + .clk(clk), + .cep(cep), + .cen(cen), + + ._reset(_reset), + .ca0(ca0), + .ca1(ca1), + .ca2(ca2), + .SEL(SEL), + .lstrb(lstrb), + ._enable(~diskEnableExt), + .writeData(writeData), + .readData(readDataExt), + .advanceDriveHead(advanceDriveHead), + .newByteReady(newByteReadyExt), + .insertDisk(insertDisk[1]), + .diskSides(diskSides[1]), + .diskEject(diskEject[1]), + + .motor(diskMotor[1]), + .act(diskAct[1]), + + .dskReadAddr(dskReadAddrExt), + .dskReadAck(dskReadAckExt), + .dskReadData(dskReadData) + ); + + wire [7:0] readData = selectExternalDrive ? readDataExt : readDataInt; + wire newByteReady = selectExternalDrive ? newByteReadyExt : newByteReadyInt; + + reg [4:0] iwmMode; + /* IWM mode register: S C M H L + S Clock speed: + 0 = 7 MHz + 1 = 8 MHz + Should always be 1 for Macintosh. + C Bit cell time: + 0 = 4 usec/bit (for 5.25 drives) + 1 = 2 usec/bit (for 3.5 drives) (Macintosh mode) + M Motor-off timer: + 0 = leave drive on for 1 sec after program turns + it off + 1 = no delay (Macintosh mode) + Should be 0 for 5.25 and 1 for 3.5. + H Handshake protocol: + 0 = synchronous (software must supply proper + timing for writing data) + 1 = asynchronous (IWM supplies timing) (Macintosh Mode) + Should be 0 for 5.25 and 1 for 3.5. + L Latch mode: + 0 = read-data stays valid for about 7 usec + 1 = read-data stays valid for full byte time (Macintosh mode) + Should be 0 for 5.25 and 1 for 3.5. + */ + + // any read/write access to IWM bit registers will change their values + always @(*) begin + ca0Next <= ca0; + ca1Next <= ca1; + ca2Next <= ca2; + lstrbNext <= lstrb; + diskEnableExtNext <= diskEnableExt; + diskEnableIntNext <= diskEnableInt; + selectExternalDriveNext <= selectExternalDrive; + q6Next <= q6; + q7Next <= q7; + + if (selectIWM == 1'b1 && _cpuLDS == 1'b0) begin + case (cpuAddrRegHi[3:1]) + 3'h0: // ca0 + ca0Next <= cpuAddrRegHi[0]; + 3'h1: // ca1 + ca1Next <= cpuAddrRegHi[0]; + 3'h2: // ca2 + ca2Next <= cpuAddrRegHi[0]; + 3'h3: // lstrb + lstrbNext <= cpuAddrRegHi[0]; + 3'h4: // disk enable + if (selectExternalDrive) + diskEnableExtNext <= cpuAddrRegHi[0]; + else + diskEnableIntNext <= cpuAddrRegHi[0]; + 3'h5: // external drive + selectExternalDriveNext <= cpuAddrRegHi[0]; + 3'h6: // Q6 + q6Next <= cpuAddrRegHi[0]; + 3'h7: // Q7 + q7Next <= cpuAddrRegHi[0]; + endcase + end + end + + // update IWM bit registers + always @(posedge clk or negedge _reset) begin + if (_reset == 1'b0) begin + ca0 <= 0; + ca1 <= 0; + ca2 <= 0; + lstrb <= 0; + diskEnableExt <= 0; + diskEnableInt <= 0; + selectExternalDrive <= 0; + q6 <= 0; + q7 <= 0; + end + else if(cen) begin + ca0 <= ca0Next; + ca1 <= ca1Next; + ca2 <= ca2Next; + lstrb <= lstrbNext; + diskEnableExt <= diskEnableExtNext; + diskEnableInt <= diskEnableIntNext; + selectExternalDrive <= selectExternalDriveNext; + q6 <= q6Next; + q7 <= q7Next; + end + end + + // read IWM state + always @(*) begin + dataOutLo = 8'hEF; + + // reading any IWM address returns state as selected by Q7 and Q6 + case ({q7Next,q6Next}) + 2'b00: // data-in register (from disk drive) - MSB is 1 when data is valid + dataOutLo <= readDataLatch; + 2'b01: // IWM status register - read only + dataOutLo <= { (selectExternalDriveNext ? senseExt : senseInt), 1'b0, diskEnableExt & diskEnableInt, iwmMode }; + 2'b10: // handshake - read only + dataOutLo <= { _iwmBusy, _writeUnderrun, 6'b000000 }; + 2'b11: // IWM mode register when not enabled (write-only), or (write?) data register when enabled + dataOutLo <= 0; + endcase + end + + // write IWM state + always @(posedge clk or negedge _reset) begin + if (_reset == 1'b0) begin + iwmMode <= 0; + writeData <= 0; + end + else if(cen) begin + if (_cpuRW == 0 && selectIWM == 1'b1 && _cpuLDS == 1'b0) begin + // writing to any IWM address modifies state as selected by Q7 and Q6 + case ({q7Next,q6Next}) + 2'b11: begin + if (diskEnableExt | diskEnableInt) + writeData <= dataInLo; + else + iwmMode <= dataInLo[4:0]; + end + endcase + end + end + end + + // Manage incoming bytes from the disk drive + wire iwmRead = (_cpuRW == 1'b1 && selectIWM == 1'b1 && _cpuLDS == 1'b0); + reg iwmReadPrev; + reg [3:0] readLatchClearTimer; + always @(posedge clk or negedge _reset) begin + if (_reset == 1'b0) begin + readDataLatch <= 0; + readLatchClearTimer <= 0; + iwmReadPrev <= 0; + end + else if(cen) begin + // a countdown timer governs how long after a data latch read before the latch is cleared + if (readLatchClearTimer != 0) begin + readLatchClearTimer <= readLatchClearTimer - 1'b1; + end + + // the conclusion of a valid CPU read from the IWM will start the timer to clear the latch + if (iwmReadPrev && !iwmRead && readDataLatch[7]) begin + readLatchClearTimer <= 4'hD; // clear latch 14 clocks after the conclusion of a valid read + end + + // when the drive indicates that a new byte is ready, latch it + // NOTE: the real IWM must self-synchronize with the incoming data to determine when to latch it + if (newByteReady) begin + readDataLatch <= readData; + end + else if (readLatchClearTimer == 1'b1) begin + readDataLatch <= 0; + end + + iwmReadPrev <= iwmRead; + end + end + assign advanceDriveHead = readLatchClearTimer == 1'b1; // prevents overrun when debugging, does not exist on a real Mac! +endmodule diff --git a/jtag.cdf b/jtag.cdf new file mode 100644 index 0000000..12760ca --- /dev/null +++ b/jtag.cdf @@ -0,0 +1,15 @@ +/* Quartus Prime Version 17.0.1 Build 598 06/07/2017 SJ Standard Edition */ +JedecChain; + FileRevision(JESD32A); + DefaultMfr(6E); + + P ActionCode(Ign) + Device PartName(SOCVHPS) MfrSpec(OpMask(0)); + P ActionCode(Cfg) + Device PartName(5CSEBA6U23) Path("output_files/") File("MacPlus.sof") MfrSpec(OpMask(1)); + +ChainEnd; + +AlteraBegin; + ChainType(JTAG); +AlteraEnd; diff --git a/jtag_lite.cdf b/jtag_lite.cdf new file mode 100644 index 0000000..1e8ec4c --- /dev/null +++ b/jtag_lite.cdf @@ -0,0 +1,15 @@ +/* Quartus Prime Version 17.0.1 Build 598 06/07/2017 SJ Standard Edition */ +JedecChain; + FileRevision(JESD32A); + DefaultMfr(6E); + + P ActionCode(Ign) + Device PartName(SOCVHPS) MfrSpec(OpMask(0)); + P ActionCode(Cfg) + Device PartName(5CSEBA6U23) Path("output_files/") File("MacPlus-lite.sof") MfrSpec(OpMask(1)); + +ChainEnd; + +AlteraBegin; + ChainType(JTAG); +AlteraEnd; diff --git a/ncr5380.v b/ncr5380.v new file mode 100644 index 0000000..84f4b9f --- /dev/null +++ b/ncr5380.v @@ -0,0 +1,297 @@ +/* verilator lint_off UNUSED */ + +/* based on minimigmac by Benjamin Herrenschmidt */ + +/* Read registers */ +`define RREG_CDR 3'h0 /* Current SCSI data */ +`define RREG_ICR 3'h1 /* Initiator Command */ +`define RREG_MR 3'h2 /* Mode register */ +`define RREG_TCR 3'h3 /* Target Command */ +`define RREG_CSR 3'h4 /* SCSI bus status */ +`define RREG_BSR 3'h5 /* Bus and status */ +`define RREG_IDR 3'h6 /* Input data */ +`define RREG_RST 3'h7 /* Reset */ + +/* Write registers */ +`define WREG_ODR 3'h0 /* Ouptut data */ +`define WREG_ICR 3'h1 /* Initiator Command */ +`define WREG_MR 3'h2 /* Mode register */ +`define WREG_TCR 3'h3 /* Target Command */ +`define WREG_SER 3'h4 /* Select Enable */ +`define WREG_DMAS 3'h5 /* Start DMA Send */ +`define WREG_DMATR 3'h6 /* Start DMA Target receive */ +`define WREG_IDMAR 3'h7 /* Start DMA Initiator receive */ + +/* MR bit numbers */ +`define MR_DMA_MODE 1 +`define MR_ARB 0 + +/* ICR bit numbers */ +`define ICR_A_RST 7 +`define ICR_TEST_MODE 6 +`define ICR_DIFF_ENBL 5 +`define ICR_A_ACK 4 +`define ICR_A_BSY 3 +`define ICR_A_SEL 2 +`define ICR_A_ATN 1 +`define ICR_A_DATA 0 + +/* TCR bit numbers */ +`define TCR_A_REQ 3 +`define TCR_A_MSG 2 +`define TCR_A_CD 1 +`define TCR_A_IO 0 + +module ncr5380 +( + input clk, + input ce, + + input reset, + + /* Bus interface. 3-bit address, to be wired + * appropriately upstream (to A4..A6) plus one + * more bit (A9) wired as dack. + */ + input bus_cs, + input bus_we, + input [2:0] bus_rs, + input dack, + input [7:0] wdata, + output [7:0] rdata, + + + // connections to io controller + output [31:0] io_lba, + output io_rd, + output io_wr, + input io_ack, + + input [8:0] sd_buff_addr, + input [7:0] sd_buff_dout, + output [7:0] sd_buff_din, + input sd_buff_wr +); + + reg [7:0] mr; /* Mode Register */ + reg [7:0] icr; /* Initiator Command Register */ + reg [3:0] tcr; /* Target Command Register */ + wire [7:0] csr; /* SCSI bus status register */ + + /* Data in and out latches and associated + * control logic for DMA + */ + wire [7:0] din; + reg [7:0] dout; + reg dphase; + reg dma_en; + + /* --- Main host-side interface --- */ + + /* Register & DMA accesses decodes */ + reg dma_rd; + reg dma_wr; + reg reg_wr; + + wire i_dma_rd = bus_cs & dack & ~bus_we; + wire i_dma_wr = bus_cs & dack & bus_we; + wire i_reg_wr = bus_cs & ~dack & bus_we; + + always @(posedge clk) begin + reg old_dma_rd, old_dma_wr, old_reg_wr; + + old_dma_rd <= i_dma_rd; + old_dma_wr <= i_dma_wr; + old_reg_wr <= i_reg_wr; + + dma_rd <= 0; + dma_wr <= 0; + reg_wr <= 0; + + if(~old_dma_wr & i_dma_wr) dma_wr <= 1; + else if(~old_dma_rd & i_dma_rd) dma_rd <= 1; + else if(~old_reg_wr & i_reg_wr) reg_wr <= 1; + end + + /* System bus reads */ + assign rdata = dack ? cur_data : + bus_rs == `RREG_CDR ? cur_data : + bus_rs == `RREG_ICR ? icr_read : + bus_rs == `RREG_MR ? mr : + bus_rs == `RREG_TCR ? { 4'h0, tcr } : + bus_rs == `RREG_CSR ? csr : + bus_rs == `RREG_BSR ? bsr : + bus_rs == `RREG_IDR ? cur_data : + bus_rs == `RREG_RST ? 8'hff : + 8'hff; + + /* DMA handhsaking logic. Two phase logic, in phase 0 + * DRQ follows SCSI _REQ until we see DACK. In phase 1 + * we just wait for SCSI _REQ to go down and go back to + * phase 0. We assert SCSI _ACK in phase 1. + */ + always@(posedge clk or posedge reset) begin + if (reset) begin + dphase <= 0; + end else begin + if (!dma_en) begin + dphase <= 0; + end else if (dphase == 0) begin + /* Be careful to do that in bus phase 1, + * not phase 0, or we would incorrectly + * assert bus_hold and lock up the system + */ + if ((dma_rd || dma_wr) && scsi_req) begin + dphase <= 1; + end + end else if (!scsi_req) begin + dphase <= 0; + end + end + end + + /* Data out latch (in DMA mode, this is one cycle after we've + * asserted ACK) + */ + always@(posedge clk) if((reg_wr && bus_rs == `WREG_ODR) || dma_wr) dout <= wdata; + + /* Current data register. Simplified logic: We loop back the + * output data if we are asserting the bus, else we get the + * input latch + */ + wire [7:0] cur_data = out_en ? dout : din; + + /* Logic for "asserting the bus" simplified */ + wire out_en = icr[`ICR_A_DATA] | mr[`MR_ARB]; + + /* ICR read wires */ + wire [7:0] icr_read = { icr[`ICR_A_RST], + icr_aip, + icr_la, + icr[`ICR_A_ACK], + icr[`ICR_A_BSY], + icr[`ICR_A_SEL], + icr[`ICR_A_ATN], + icr[`ICR_A_DATA] }; + + /* ICR write */ + always@(posedge clk or posedge reset) begin + if (reset) begin + icr <= 0; + end else if (reg_wr && (bus_rs == `WREG_ICR)) begin + icr <= wdata; + end + end + + /* MR write */ + always@(posedge clk or posedge reset) begin + if (reset) mr <= 8'b0; + else if (reg_wr && (bus_rs == `WREG_MR)) mr <= wdata; + end + + /* TCR write */ + always@(posedge clk or posedge reset) begin + if (reset) tcr <= 4'b0; + else if (reg_wr && (bus_rs == `WREG_TCR)) tcr <= wdata[3:0]; + end + + /* DMA start send & receive registers. We currently ignore + * the direction. + */ + always@(posedge clk or posedge reset) begin + if (reset) begin + dma_en <= 0; + end else begin + if (!mr[`MR_DMA_MODE]) begin + dma_en <= 0; + end else if (reg_wr && (bus_rs == `WREG_DMAS)) begin + dma_en <= 1; + end else if (reg_wr && (bus_rs == `WREG_IDMAR)) begin + dma_en <= 1; + end + end + end + + /* CSR (read only). We don't do parity */ + assign csr = { scsi_rst, scsi_bsy, scsi_req, scsi_msg, + scsi_cd, scsi_io, scsi_sel, 1'b0 }; + + /* Bus and Status register */ + /* BSR (read only). We don't do a few things... */ + wire bsr_eodma = 1'b0; /* We don't do EOP */ + wire bsr_dmarq = scsi_req & dma_en; + wire bsr_perr = 1'b0; /* We don't do parity */ + wire bsr_irq = 1'b0; /* XXX ? Does MacOS use this ? */ + wire bsr_pmatch = + tcr[`TCR_A_MSG] == scsi_msg && + tcr[`TCR_A_CD ] == scsi_cd && + tcr[`TCR_A_IO ] == scsi_io; + + wire bsr_berr = 1'b0; /* XXX ? Does MacOS use this ? */ + wire [7:0] bsr = { bsr_eodma, bsr_dmarq, bsr_perr, bsr_irq, + bsr_pmatch, bsr_berr, scsi_atn, scsi_ack }; + + /* --- Simulated SCSI Signals --- */ + + /* BSY logic (simplified arbitration, see notes) */ + wire scsi_bsy = + icr[`ICR_A_BSY] | + scsi2_bsy | + mr[`MR_ARB]; + + /* Remains of simplified arbitration logic */ + wire icr_aip = mr[`MR_ARB]; + wire icr_la = 0; + + reg dma_ack; + always @(posedge clk) if(ce) dma_ack <= dphase; + + /* Other ORed SCSI signals */ + wire scsi_sel = icr[`ICR_A_SEL]; + wire scsi_rst = icr[`ICR_A_RST]; + wire scsi_ack = icr[`ICR_A_ACK] | dma_ack; + wire scsi_atn = icr[`ICR_A_ATN]; + + /* Other trivial lines set by target */ + wire scsi_cd = scsi2_cd; + wire scsi_io = scsi2_io; + wire scsi_msg = scsi2_msg; + wire scsi_req = scsi2_req; + + assign din = scsi2_bsy?scsi2_dout:8'h55; + + // input signals from target 2 + wire scsi2_bsy, scsi2_msg, scsi2_io, scsi2_cd, scsi2_req; + wire [7:0] scsi2_dout; + + // connect a target + scsi #(.ID(2)) scsi2 + ( + .clk ( clk ), + .rst ( scsi_rst ), + .sel ( scsi_sel ), + .atn ( scsi_atn ), + .bsy ( scsi2_bsy ), + .msg ( scsi2_msg ), + .cd ( scsi2_cd ), + .io ( scsi2_io ), + .req ( scsi2_req ), + .ack ( scsi_ack ), + .dout ( scsi2_dout ), + .din ( dout ), + + // connection to io controller to read and write sectors + // to sd card + .io_lba ( io_lba ), + .io_rd ( io_rd ), + .io_wr ( io_wr ), + .io_ack ( io_ack ), + + .sd_buff_addr(sd_buff_addr), + .sd_buff_dout(sd_buff_dout), + .sd_buff_din(sd_buff_din), + .sd_buff_wr(sd_buff_wr) + ); + + +endmodule diff --git a/ps2_kbd.sv b/ps2_kbd.sv new file mode 100644 index 0000000..11b5542 --- /dev/null +++ b/ps2_kbd.sv @@ -0,0 +1,654 @@ +`timescale 1ns / 100ps + +/* + * PS2 Keyboard to Mac interface module + */ +module ps2_kbd +( + input clk, + input ce, + + input reset, + + input [64:0] ps2_key, + output reg capslock, + + input [7:0] data_out, + input strobe_out, + + output [7:0] data_in, + output strobe_in +); + +reg [8:0] keymac; +reg key_pending; +reg [21:0] pacetimer; +reg inquiry_active; +reg cmd_inquiry; +reg cmd_instant; +reg cmd_model; +reg cmd_test; + +/* Latch commands from Mac */ +always@(posedge clk or posedge reset) begin + if (reset) begin + cmd_inquiry <= 0; + cmd_instant <= 0; + cmd_model <= 0; + cmd_test <= 0; + end else if(ce) begin + if (strobe_out) begin + cmd_inquiry <= 0; + cmd_instant <= 0; + cmd_model <= 0; + cmd_test <= 0; + case(data_out) + 8'h10: cmd_inquiry <= 1; + 8'h14: cmd_instant <= 1; + 8'h16: cmd_model <= 1; + 8'h36: cmd_test <= 1; + endcase + end + end +end + +/* Divide our clock to pace our responses to the Mac. tick_short ticks + * when we can respond to a command, and tick_long ticks when an inquiry + * command shall timeout + */ +always@(posedge clk or posedge reset) begin + if (reset) + pacetimer <= 0; + else if(ce) begin + /* reset counter on command from Mac */ + if (strobe_out) + pacetimer <= 0; + else if (!tick_long) + pacetimer <= pacetimer + 1'd1; + end +end + +wire tick_long = pacetimer == 22'h3fffff; +wire tick_short = pacetimer == 22'h000fff; + +/* Delay inquiry responses to after tick_short */ +always@(posedge clk or posedge reset) begin + if (reset) + inquiry_active <= 0; + else if(ce) begin + if (strobe_out | strobe_in) + inquiry_active <= 0; + else if (tick_short) + inquiry_active <= cmd_inquiry; + end +end + +wire pop_key = (cmd_instant & tick_short) | (inquiry_active & tick_long) | (inquiry_active & key_pending); + +/* Reply to Mac */ +assign strobe_in = ((cmd_model | cmd_test) & tick_short) | pop_key; + +/* Data to Mac */ +assign data_in = cmd_test ? 8'h7d : + cmd_model ? 8'h03 : + key_pending ? (keymac[8] ? 8'h79 : keymac[7:0]) : + 8'h7b; + +wire depress = (ps2_key[15:8] == 8'hf0) /* synthesis keep */; +wire extended = (depress ? (ps2_key[23:16] == 8'he0) : (ps2_key[15:8] == 8'he0)) /* synthesis keep */; +wire ignore_capslock = {extended,ps2_key[7:0]} == 9'h058 && capslock; + +/* Handle key_pending, and multi-byte keypad responses */ +always @(posedge clk) begin + reg old_stb; + + if (reset) begin + key_pending <= 0; + old_stb <= ps2_key[64]; + capslock <= 0; + end + else if(ce) begin + if (cmd_model | cmd_test) key_pending <= 0; + else if (pop_key) begin + if (keymac[8]) keymac[8] <= 0; + else key_pending <= 0; + end else begin + + old_stb <= ps2_key[64]; + if(old_stb != ps2_key[64]) begin + + /* Capslock handling */ + if(ps2_key[7:0] == 8'h58 && !extended && !depress) capslock <= ~capslock; + + if(!key_pending && !ignore_capslock && !ps2_key[63:24]) begin + key_pending <= 1; + keymac <= {key_code[8],depress,key_code[6:0]}; + end + end + end + end +end + + +//use BRAM for table +wire [8:0] key_code = code[key_addr]; +reg [8:0] key_addr; +always @(posedge clk) key_addr <= {extended,ps2_key[7:0]}; + +wire [8:0] code[512] = +'{ + /* 000 */ 9'h07b, + /* 001 */ 9'h07b, //F9 + /* 002 */ 9'h07b, + /* 003 */ 9'h07b, //F5 + /* 004 */ 9'h07b, //F3 + /* 005 */ 9'h07b, //F1 + /* 006 */ 9'h07b, //F2 + /* 007 */ 9'h07b, //F12 + /* 008 */ 9'h07b, + /* 009 */ 9'h07b, //F10 + /* 00a */ 9'h07b, //F8 + /* 00b */ 9'h07b, //F6 + /* 00c */ 9'h07b, //F4 + /* 00d */ 9'h061, //TAB + /* 00e */ 9'h065, //~ (`) + /* 00f */ 9'h07b, + /* 010 */ 9'h07b, + /* 011 */ 9'h06f, //LEFT ALT (command) + /* 012 */ 9'h071, //LEFT SHIFT + /* 013 */ 9'h07b, + /* 014 */ 9'h07b, //CTRL (not mapped) + /* 015 */ 9'h019, //q + /* 016 */ 9'h025, //1 + /* 017 */ 9'h07b, + /* 018 */ 9'h07b, + /* 019 */ 9'h07b, + /* 01a */ 9'h00d, //z + /* 01b */ 9'h003, //s + /* 01c */ 9'h001, //a + /* 01d */ 9'h01b, //w + /* 01e */ 9'h027, //2 + /* 01f */ 9'h07b, + /* 020 */ 9'h07b, + /* 021 */ 9'h011, //c + /* 022 */ 9'h00f, //x + /* 023 */ 9'h005, //d + /* 024 */ 9'h01d, //e + /* 025 */ 9'h02b, //4 + /* 026 */ 9'h029, //3 + /* 027 */ 9'h07b, + /* 028 */ 9'h07b, + /* 029 */ 9'h063, //SPACE + /* 02a */ 9'h013, //v + /* 02b */ 9'h007, //f + /* 02c */ 9'h023, //t + /* 02d */ 9'h01f, //r + /* 02e */ 9'h02f, //5 + /* 02f */ 9'h07b, + /* 030 */ 9'h07b, + /* 031 */ 9'h05b, //n + /* 032 */ 9'h017, //b + /* 033 */ 9'h009, //h + /* 034 */ 9'h00b, //g + /* 035 */ 9'h021, //y + /* 036 */ 9'h02d, //6 + /* 037 */ 9'h07b, + /* 038 */ 9'h07b, + /* 039 */ 9'h07b, + /* 03a */ 9'h05d, //m + /* 03b */ 9'h04d, //j + /* 03c */ 9'h041, //u + /* 03d */ 9'h035, //7 + /* 03e */ 9'h039, //8 + /* 03f */ 9'h07b, + /* 040 */ 9'h07b, + /* 041 */ 9'h057, //<, + /* 042 */ 9'h051, //k + /* 043 */ 9'h045, //i + /* 044 */ 9'h03f, //o + /* 045 */ 9'h03b, //0 + /* 046 */ 9'h033, //9 + /* 047 */ 9'h07b, + /* 048 */ 9'h07b, + /* 049 */ 9'h05f, //>. + /* 04a */ 9'h059, //FORWARD SLASH + /* 04b */ 9'h04b, //l + /* 04c */ 9'h053, //; + /* 04d */ 9'h047, //p + /* 04e */ 9'h037, //- + /* 04f */ 9'h07b, + /* 050 */ 9'h07b, + /* 051 */ 9'h07b, + /* 052 */ 9'h04f, //'" + /* 053 */ 9'h07b, + /* 054 */ 9'h043, //[ + /* 055 */ 9'h031, // = + /* 056 */ 9'h07b, + /* 057 */ 9'h07b, + /* 058 */ 9'h073, //CAPSLOCK + /* 059 */ 9'h071, //RIGHT SHIFT + /* 05a */ 9'h049, //ENTER + /* 05b */ 9'h03d, //] + /* 05c */ 9'h07b, + /* 05d */ 9'h055, //BACKSLASH + /* 05e */ 9'h07b, + /* 05f */ 9'h07b, + /* 060 */ 9'h07b, + /* 061 */ 9'h071, //international left shift cut out (German '<>' key), 0x56 Set#1 code + /* 062 */ 9'h07b, + /* 063 */ 9'h07b, + /* 064 */ 9'h07b, + /* 065 */ 9'h07b, + /* 066 */ 9'h067, //BACKSPACE + /* 067 */ 9'h07b, + /* 068 */ 9'h07b, + /* 069 */ 9'h127, //KP 1 + /* 06a */ 9'h07b, + /* 06b */ 9'h12d, //KP 4 + /* 06c */ 9'h133, //KP 7 + /* 06d */ 9'h07b, + /* 06e */ 9'h07b, + /* 06f */ 9'h07b, + /* 070 */ 9'h125, //KP 0 + /* 071 */ 9'h103, //KP . + /* 072 */ 9'h129, //KP 2 + /* 073 */ 9'h12f, //KP 5 + /* 074 */ 9'h131, //KP 6 + /* 075 */ 9'h137, //KP 8 + /* 076 */ 9'h07b, //ESCAPE + /* 077 */ 9'h07b, //NUMLOCK (Mac keypad clear?) + /* 078 */ 9'h07b, //F11 + /* 079 */ 9'h10d, //KP + + /* 07a */ 9'h12b, //KP 3 + /* 07b */ 9'h11d, //KP - + /* 07c */ 9'h105, //KP * + /* 07d */ 9'h139, //KP 9 + /* 07e */ 9'h07b, //SCROLL LOCK / KP ) + /* 07f */ 9'h07b, + /* 080 */ 9'h07b, + /* 081 */ 9'h07b, + /* 082 */ 9'h07b, + /* 083 */ 9'h07b, //F7 + /* 084 */ 9'h07b, + /* 085 */ 9'h07b, + /* 086 */ 9'h07b, + /* 087 */ 9'h07b, + /* 088 */ 9'h07b, + /* 089 */ 9'h07b, + /* 08a */ 9'h07b, + /* 08b */ 9'h07b, + /* 08c */ 9'h07b, + /* 08d */ 9'h07b, + /* 08e */ 9'h07b, + /* 08f */ 9'h07b, + /* 090 */ 9'h07b, + /* 091 */ 9'h07b, + /* 092 */ 9'h07b, + /* 093 */ 9'h07b, + /* 094 */ 9'h07b, + /* 095 */ 9'h07b, + /* 096 */ 9'h07b, + /* 097 */ 9'h07b, + /* 098 */ 9'h07b, + /* 099 */ 9'h07b, + /* 09a */ 9'h07b, + /* 09b */ 9'h07b, + /* 09c */ 9'h07b, + /* 09d */ 9'h07b, + /* 09e */ 9'h07b, + /* 09f */ 9'h07b, + /* 0a0 */ 9'h07b, + /* 0a1 */ 9'h07b, + /* 0a2 */ 9'h07b, + /* 0a3 */ 9'h07b, + /* 0a4 */ 9'h07b, + /* 0a5 */ 9'h07b, + /* 0a6 */ 9'h07b, + /* 0a7 */ 9'h07b, + /* 0a8 */ 9'h07b, + /* 0a9 */ 9'h07b, + /* 0aa */ 9'h07b, + /* 0ab */ 9'h07b, + /* 0ac */ 9'h07b, + /* 0ad */ 9'h07b, + /* 0ae */ 9'h07b, + /* 0af */ 9'h07b, + /* 0b0 */ 9'h07b, + /* 0b1 */ 9'h07b, + /* 0b2 */ 9'h07b, + /* 0b3 */ 9'h07b, + /* 0b4 */ 9'h07b, + /* 0b5 */ 9'h07b, + /* 0b6 */ 9'h07b, + /* 0b7 */ 9'h07b, + /* 0b8 */ 9'h07b, + /* 0b9 */ 9'h07b, + /* 0ba */ 9'h07b, + /* 0bb */ 9'h07b, + /* 0bc */ 9'h07b, + /* 0bd */ 9'h07b, + /* 0be */ 9'h07b, + /* 0bf */ 9'h07b, + /* 0c0 */ 9'h07b, + /* 0c1 */ 9'h07b, + /* 0c2 */ 9'h07b, + /* 0c3 */ 9'h07b, + /* 0c4 */ 9'h07b, + /* 0c5 */ 9'h07b, + /* 0c6 */ 9'h07b, + /* 0c7 */ 9'h07b, + /* 0c8 */ 9'h07b, + /* 0c9 */ 9'h07b, + /* 0ca */ 9'h07b, + /* 0cb */ 9'h07b, + /* 0cc */ 9'h07b, + /* 0cd */ 9'h07b, + /* 0ce */ 9'h07b, + /* 0cf */ 9'h07b, + /* 0d0 */ 9'h07b, + /* 0d1 */ 9'h07b, + /* 0d2 */ 9'h07b, + /* 0d3 */ 9'h07b, + /* 0d4 */ 9'h07b, + /* 0d5 */ 9'h07b, + /* 0d6 */ 9'h07b, + /* 0d7 */ 9'h07b, + /* 0d8 */ 9'h07b, + /* 0d9 */ 9'h07b, + /* 0da */ 9'h07b, + /* 0db */ 9'h07b, + /* 0dc */ 9'h07b, + /* 0dd */ 9'h07b, + /* 0de */ 9'h07b, + /* 0df */ 9'h07b, + /* 0e0 */ 9'h07b, //ps2 extended key + /* 0e1 */ 9'h07b, + /* 0e2 */ 9'h07b, + /* 0e3 */ 9'h07b, + /* 0e4 */ 9'h07b, + /* 0e5 */ 9'h07b, + /* 0e6 */ 9'h07b, + /* 0e7 */ 9'h07b, + /* 0e8 */ 9'h07b, + /* 0e9 */ 9'h07b, + /* 0ea */ 9'h07b, + /* 0eb */ 9'h07b, + /* 0ec */ 9'h07b, + /* 0ed */ 9'h07b, + /* 0ee */ 9'h07b, + /* 0ef */ 9'h07b, + /* 0f0 */ 9'h07b, //ps2 release code + /* 0f1 */ 9'h07b, + /* 0f2 */ 9'h07b, + /* 0f3 */ 9'h07b, + /* 0f4 */ 9'h07b, + /* 0f5 */ 9'h07b, + /* 0f6 */ 9'h07b, + /* 0f7 */ 9'h07b, + /* 0f8 */ 9'h07b, + /* 0f9 */ 9'h07b, + /* 0fa */ 9'h07b, //ps2 ack code + /* 0fb */ 9'h07b, + /* 0fc */ 9'h07b, + /* 0fd */ 9'h07b, + /* 0fe */ 9'h07b, + /* 0ff */ 9'h07b, + /* 100 */ 9'h07b, + /* 101 */ 9'h07b, + /* 102 */ 9'h07b, + /* 103 */ 9'h07b, + /* 104 */ 9'h07b, + /* 105 */ 9'h07b, + /* 106 */ 9'h07b, + /* 107 */ 9'h07b, + /* 108 */ 9'h07b, + /* 109 */ 9'h07b, + /* 10a */ 9'h07b, + /* 10b */ 9'h07b, + /* 10c */ 9'h07b, + /* 10d */ 9'h07b, + /* 10e */ 9'h07b, + /* 10f */ 9'h07b, + /* 110 */ 9'h07b, + /* 111 */ 9'h06f, //RIGHT ALT (command) + /* 112 */ 9'h07b, + /* 113 */ 9'h07b, + /* 114 */ 9'h07b, + /* 115 */ 9'h07b, + /* 116 */ 9'h07b, + /* 117 */ 9'h07b, + /* 118 */ 9'h07b, + /* 119 */ 9'h07b, + /* 11a */ 9'h07b, + /* 11b */ 9'h07b, + /* 11c */ 9'h07b, + /* 11d */ 9'h07b, + /* 11e */ 9'h07b, + /* 11f */ 9'h075, //WINDOWS OR APPLICATION KEY (option) + /* 120 */ 9'h07b, + /* 121 */ 9'h07b, + /* 122 */ 9'h07b, + /* 123 */ 9'h07b, + /* 124 */ 9'h07b, + /* 125 */ 9'h07b, + /* 126 */ 9'h07b, + /* 127 */ 9'h07b, + /* 128 */ 9'h07b, + /* 129 */ 9'h07b, + /* 12a */ 9'h07b, + /* 12b */ 9'h07b, + /* 12c */ 9'h07b, + /* 12d */ 9'h07b, + /* 12e */ 9'h07b, + /* 12f */ 9'h07b, + /* 130 */ 9'h07b, + /* 131 */ 9'h07b, + /* 132 */ 9'h07b, + /* 133 */ 9'h07b, + /* 134 */ 9'h07b, + /* 135 */ 9'h07b, + /* 136 */ 9'h07b, + /* 137 */ 9'h07b, + /* 138 */ 9'h07b, + /* 139 */ 9'h07b, + /* 13a */ 9'h07b, + /* 13b */ 9'h07b, + /* 13c */ 9'h07b, + /* 13d */ 9'h07b, + /* 13e */ 9'h07b, + /* 13f */ 9'h07b, + /* 140 */ 9'h07b, + /* 141 */ 9'h07b, + /* 142 */ 9'h07b, + /* 143 */ 9'h07b, + /* 144 */ 9'h07b, + /* 145 */ 9'h07b, + /* 146 */ 9'h07b, + /* 147 */ 9'h07b, + /* 148 */ 9'h07b, + /* 149 */ 9'h07b, + /* 14a */ 9'h11b, //KP / + /* 14b */ 9'h07b, + /* 14c */ 9'h07b, + /* 14d */ 9'h07b, + /* 14e */ 9'h07b, + /* 14f */ 9'h07b, + /* 150 */ 9'h07b, + /* 151 */ 9'h07b, + /* 152 */ 9'h07b, + /* 153 */ 9'h07b, + /* 154 */ 9'h07b, + /* 155 */ 9'h07b, + /* 156 */ 9'h07b, + /* 157 */ 9'h07b, + /* 158 */ 9'h07b, + /* 159 */ 9'h07b, + /* 15a */ 9'h119, //KP ENTER + /* 15b */ 9'h07b, + /* 15c */ 9'h07b, + /* 15d */ 9'h07b, + /* 15e */ 9'h07b, + /* 15f */ 9'h07b, + /* 160 */ 9'h07b, + /* 161 */ 9'h07b, + /* 162 */ 9'h07b, + /* 163 */ 9'h07b, + /* 164 */ 9'h07b, + /* 165 */ 9'h07b, + /* 166 */ 9'h07b, + /* 167 */ 9'h07b, + /* 168 */ 9'h07b, + /* 169 */ 9'h07b, //END + /* 16a */ 9'h07b, + /* 16b */ 9'h10d, //ARROW LEFT + /* 16c */ 9'h07b, //HOME + /* 16d */ 9'h07b, + /* 16e */ 9'h07b, + /* 16f */ 9'h07b, + /* 170 */ 9'h07b, //INSERT = HELP + /* 171 */ 9'h10f, //DELETE (KP clear?) + /* 172 */ 9'h111, //ARROW DOWN + /* 173 */ 9'h07b, + /* 174 */ 9'h105, //ARROW RIGHT + /* 175 */ 9'h11b, //ARROW UP + /* 176 */ 9'h07b, + /* 177 */ 9'h07b, + /* 178 */ 9'h07b, + /* 179 */ 9'h07b, + /* 17a */ 9'h07b, //PGDN + /* 17b */ 9'h07b, + /* 17c */ 9'h07b, //PRTSCR + /* 17d */ 9'h07b, //PGUP + /* 17e */ 9'h07b, //ctrl+break + /* 17f */ 9'h07b, + /* 180 */ 9'h07b, + /* 181 */ 9'h07b, + /* 182 */ 9'h07b, + /* 183 */ 9'h07b, + /* 184 */ 9'h07b, + /* 185 */ 9'h07b, + /* 186 */ 9'h07b, + /* 187 */ 9'h07b, + /* 188 */ 9'h07b, + /* 189 */ 9'h07b, + /* 18a */ 9'h07b, + /* 18b */ 9'h07b, + /* 18c */ 9'h07b, + /* 18d */ 9'h07b, + /* 18e */ 9'h07b, + /* 18f */ 9'h07b, + /* 190 */ 9'h07b, + /* 191 */ 9'h07b, + /* 192 */ 9'h07b, + /* 193 */ 9'h07b, + /* 194 */ 9'h07b, + /* 195 */ 9'h07b, + /* 196 */ 9'h07b, + /* 197 */ 9'h07b, + /* 198 */ 9'h07b, + /* 199 */ 9'h07b, + /* 19a */ 9'h07b, + /* 19b */ 9'h07b, + /* 19c */ 9'h07b, + /* 19d */ 9'h07b, + /* 19e */ 9'h07b, + /* 19f */ 9'h07b, + /* 1a0 */ 9'h07b, + /* 1a1 */ 9'h07b, + /* 1a2 */ 9'h07b, + /* 1a3 */ 9'h07b, + /* 1a4 */ 9'h07b, + /* 1a5 */ 9'h07b, + /* 1a6 */ 9'h07b, + /* 1a7 */ 9'h07b, + /* 1a8 */ 9'h07b, + /* 1a9 */ 9'h07b, + /* 1aa */ 9'h07b, + /* 1ab */ 9'h07b, + /* 1ac */ 9'h07b, + /* 1ad */ 9'h07b, + /* 1ae */ 9'h07b, + /* 1af */ 9'h07b, + /* 1b0 */ 9'h07b, + /* 1b1 */ 9'h07b, + /* 1b2 */ 9'h07b, + /* 1b3 */ 9'h07b, + /* 1b4 */ 9'h07b, + /* 1b5 */ 9'h07b, + /* 1b6 */ 9'h07b, + /* 1b7 */ 9'h07b, + /* 1b8 */ 9'h07b, + /* 1b9 */ 9'h07b, + /* 1ba */ 9'h07b, + /* 1bb */ 9'h07b, + /* 1bc */ 9'h07b, + /* 1bd */ 9'h07b, + /* 1be */ 9'h07b, + /* 1bf */ 9'h07b, + /* 1c0 */ 9'h07b, + /* 1c1 */ 9'h07b, + /* 1c2 */ 9'h07b, + /* 1c3 */ 9'h07b, + /* 1c4 */ 9'h07b, + /* 1c5 */ 9'h07b, + /* 1c6 */ 9'h07b, + /* 1c7 */ 9'h07b, + /* 1c8 */ 9'h07b, + /* 1c9 */ 9'h07b, + /* 1ca */ 9'h07b, + /* 1cb */ 9'h07b, + /* 1cc */ 9'h07b, + /* 1cd */ 9'h07b, + /* 1ce */ 9'h07b, + /* 1cf */ 9'h07b, + /* 1d0 */ 9'h07b, + /* 1d1 */ 9'h07b, + /* 1d2 */ 9'h07b, + /* 1d3 */ 9'h07b, + /* 1d4 */ 9'h07b, + /* 1d5 */ 9'h07b, + /* 1d6 */ 9'h07b, + /* 1d7 */ 9'h07b, + /* 1d8 */ 9'h07b, + /* 1d9 */ 9'h07b, + /* 1da */ 9'h07b, + /* 1db */ 9'h07b, + /* 1dc */ 9'h07b, + /* 1dd */ 9'h07b, + /* 1de */ 9'h07b, + /* 1df */ 9'h07b, + /* 1e0 */ 9'h07b, //ps2 extended key(duplicate, see $e0) + /* 1e1 */ 9'h07b, + /* 1e2 */ 9'h07b, + /* 1e3 */ 9'h07b, + /* 1e4 */ 9'h07b, + /* 1e5 */ 9'h07b, + /* 1e6 */ 9'h07b, + /* 1e7 */ 9'h07b, + /* 1e8 */ 9'h07b, + /* 1e9 */ 9'h07b, + /* 1ea */ 9'h07b, + /* 1eb */ 9'h07b, + /* 1ec */ 9'h07b, + /* 1ed */ 9'h07b, + /* 1ee */ 9'h07b, + /* 1ef */ 9'h07b, + /* 1f0 */ 9'h07b, //ps2 release code(duplicate, see $f0) + /* 1f1 */ 9'h07b, + /* 1f2 */ 9'h07b, + /* 1f3 */ 9'h07b, + /* 1f4 */ 9'h07b, + /* 1f5 */ 9'h07b, + /* 1f6 */ 9'h07b, + /* 1f7 */ 9'h07b, + /* 1f8 */ 9'h07b, + /* 1f9 */ 9'h07b, + /* 1fa */ 9'h07b, //ps2 ack code(duplicate see $fa) + /* 1fb */ 9'h07b, + /* 1fc */ 9'h07b, + /* 1fd */ 9'h07b, + /* 1fe */ 9'h07b, + /* 1ff */ 9'h07b +}; + +endmodule diff --git a/ps2_mouse.v b/ps2_mouse.v new file mode 100644 index 0000000..aaa1e46 --- /dev/null +++ b/ps2_mouse.v @@ -0,0 +1,94 @@ +`timescale 1ns / 100ps + +/* + * PS2 mouse protocol + * Bit 7 6 5 4 3 2 1 0 + * Byte 0: YOVR XOVR YSGN XSGN 1 MBUT RBUT LBUT + * Byte 1: XMOVE + * Byte 2: YMOVE + */ + +/* + * PS2 Mouse to Mac interface module + */ +module ps2_mouse +( + input clk, + input ce, + + input reset, + + input [24:0] ps2_mouse, + + output reg x1, + output reg y1, + output reg x2, + output reg y2, + output reg button +); + +reg [9:0] xacc; +reg [9:0] yacc; +reg [11:0] clkdiv; + +wire strobe = (old_stb != ps2_mouse[24]); +reg old_stb = 0; +always @(posedge clk) old_stb <= ps2_mouse[24]; + +/* Capture button state */ +always@(posedge clk or posedge reset) + if (reset) button <= 1; + else if (strobe) button <= ~(|ps2_mouse[2:0]); + +/* Clock divider to flush accumulators */ +always@(posedge clk or posedge reset) + if (reset) clkdiv <= 0; + else if(ce) clkdiv <= clkdiv + 1'b1; + +wire tick = (ce && clkdiv == 0); + +/* Toggle output lines base on accumulator */ +always@(posedge clk or posedge reset) begin + if (reset) begin + x1 <= 0; + x2 <= 0; + end else if (tick && xacc != 0) begin + x1 <= ~x1; + x2 <= ~x1 ^ ~xacc[9]; + end +end + +always@(posedge clk or posedge reset) begin + if (reset) begin + y1 <= 0; + y2 <= 0; + end else if (tick && yacc != 0) begin + y1 <= ~y1; + y2 <= ~y1 ^ ~yacc[9]; + end +end + +/* Movement accumulators. Needs tuning ! */ +always@(posedge clk or posedge reset) begin + if (reset) xacc <= 0; + else begin + /* Add movement, convert to a 10-bit number if not over */ + if (strobe && xacc[8] == xacc[9]) xacc <= xacc + { ps2_mouse[4], ps2_mouse[4], ps2_mouse[15:8] }; + else + /* Decrement */ + if (tick && xacc != 0) xacc <= xacc + { {9{~xacc[9]}}, 1'b1 }; + end +end + +always@(posedge clk or posedge reset) begin + if (reset) yacc <= 0; + else begin + /* Add movement, convert to a 10-bit number if not over*/ + if (strobe && yacc[8] == yacc[9]) yacc <= yacc + { ps2_mouse[5], ps2_mouse[5], ps2_mouse[23:16] }; + else + /* Decrement */ + if (tick && yacc != 0) yacc <= yacc + { {9{~yacc[9]}}, 1'b1 }; + end +end + +endmodule diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..f495302 --- /dev/null +++ b/readme.md @@ -0,0 +1,51 @@ +# Macintosh Plus for the [MiSTer Board](https://github.com/MiSTer-devel/Main_MiSTer/wiki) + +This is a port of the [Plus Too core](https://github.com/mist-devel/mist-binaries/tree/master/cores/plus_too) from MiST which is the port of the [Plus Too project](http://www.bigmessowires.com/plus-too/). + +I've tried to optimize the code with converting to synchronous style and fixing some glitches and instabilities. + + +## Usage + +* Copy the [*.rbf](https://github.com/MiSTer-devel/MacPlus_MiSTer/tree/master/releases) onto the root of SD card +* Copy the [boot.rom](https://github.com/MiSTer-devel/MacPlus_MiSTer/tree/master/releases) to MacPlus folder +* Copy disk images in dsk format (e.g. Disk605.dsk) to MacPlus folder + +After a few seconds the floppy disk icon should +appear. Open the on screen display using the F12 key and select the +a disk image. The upload of the disk image will take a few seconds. MacPlus will then boot into the MacOS desktop. + +## Floppy disk image format + +Floppy disk images need to be in raw disk format. Double sided 800k disk images have to be exactly 819200 bytes in size. Single sided 400k disk images have to be exactly 409600 bytes in size. + +Both the internal as well as the external floppy disk are supported. The first entry in the OSD refers to the internal floppy disk, the second one to the external floppy disk. + +Currently floppy disk images cannot be loaded while the Mac accesses a floppy disk. Thus it's recommended to wait for the desktop to appear until a second floppy can be inserted. + +Before loading a different disk image it's recommended to eject the previously inserted disk image from within MacOS. + +Some system floppy disk images in matching dsk format can be found at [here](http://www.rolli.ch/MacPlus/welcome.html). Some nice applicatons on 400k dsk images can be found [here](http://tkc8800.com/page/Macintosh-128k-512k-disk-images). Official system disk images are available from apple e.g. via [ftp](http://ftp.iinet.net.au/pub/apple/US/Macintosh/System/Older_System/System_6.0.x/). Under Linux these can be converted into the desired dsk format using [Linux stuffit](http://web.archive.org/web/20060205025441/http://www.stuffit.com/downloads/files/stuffit520.611linux-i386.tar.gz), unar and [dc2dsk](http://www.bigmessowires.com/dc2dsk.c) in that order. + +## Hard disk support + +This MacPlus core implements the SCSI interface of the Macintosh Plus together with a 20MB harddisk. The core implements only a subset of the SCSI commands. This is currently sufficient to read and write the disk, to boot from it and to format it using the setup tools that come with MacOS 6.0.8. + +The harddisk image to be used can be selected from the "Mount *.vhd" entry in the on-screen-display. Copy the boot.vhd to MacPlus folder and it will be automatically mounted at start. The format of the disk image is the same as being used by the SCSI2SD project which is documented [here](http://www.codesrc.com/mediawiki/index.php?title=HFSFromScratch). + +Unlike the floppy the SCSI disk is writable and data can be written to the disk from within the core. + +It has been tested that OS 6.0.8 can format the SCSI disk as well as doing a full installation from floppy disk to the harddisk. But keep in mind that this is an early work in progress and expect data loss when working with HDD images. + +A matching harddisk image file can be found [here](https://github.com/MiSTer-devel/MacPlus_MiSTer/tree/master/releases). This is a 20MB harddisk image with correct partitioning information and a basic SCSI driver installed. The data partition itself is empty and unformatted. After booting the Mac will thus ask whether the disk is to be initialized. Saying yes and giving the disk a name will result im a usable file system. You don't need to use the Setup tool to format this disk as it is already formatted. But you can format it if you want to. This is only been tested with OS 6.0.8. + +## CPU Speed + +The CPU speed can be adjusted from "normal" which is roughly Mac Plus speed to "Fast" which is about 2.5 times faster. Original core couldn't boot from SCSI in turbo mode. This port has workaround to let it boot even with turbo mode. + +## Memory + +512KB, 1MB and 4MB memory configs are available. Cold boot with 4MB RAM selected takes some time before it start to boot from FDD/SCSI, so be patient. Warm boot won't take long time. + +## Keyboard +The Alt key is mapped to the Mac's command key, and the Windows key is mapped to the Mac's option key. Core emulates keyboard with keypad. diff --git a/release/Disk605.dsk b/release/Disk605.dsk new file mode 100644 index 0000000000000000000000000000000000000000..6949b2d13ac959653ce6fae835530091864cc4fb GIT binary patch literal 819200 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%0D{ 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

8u;his`X$I5-XxEw3VtKRGf-$GdWfxSV& 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�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⪻d}@2sB$8;bF8(Ts_HvDDaR!68Lks>h zR!V;GZv1ay?X}k>BY&LEKyC)+V!*CD z`Wh{OJ(<)3ERst%VJCo=BY86Hx%>8t#L;4;<51JQjj6HEM{DCwp9*g^&VvCb;r%t3 z;$MN0_ytIZpOA^LIS(GI>aG$N0_o?#KA+*ljMgyH+70KbA(RW(A&rvI7$o`#p3YG^ zWfLI}N-`Sa^LNb|2#Hfyjf5Hf@=9D*3%U?n#GOgcqMbP2id*lbF-|V@uJ{aGN=be- zFrI%c9oK+#3a(2h|0n5yd!bMh2Md%<4M{^t#XY2cW*5C-Q*c$W>LmY;4|b`jKEZNO z3MbBV7MOGkALJawSpztTq0mDW&0^U!HVslBvEu3at>Q_{bHPMSPT<=X6ANFPVPGiQ zO9?Sb$e#8?DFJm7`2a`#HnbqPnOe>%2-KcrYt=t#NAv)-mVX9OGpQZ@R;WjU!|3&Hr%mVbiQR)RjRo@r7l6nHQ;%nGI ztw@^f=W9jjFNx`|)m1lYb(ZIh`d%#v)RE3D;vkoe`e5yF3eO2@iTLaN!O8AzM~vgf zIPv(gRRT$F>s%hb-*+~AF9m$h_xq;9w`=zbM@TI8 zb5Cy*FWHPJ%UMSldg>z9n#ePj!N1E!E80u&0se5Gi}5N6PnBzk$`z|laO{;ZsW&1C zv*L9ve&**|ocDY9Px_t7jD3B5<&u<(;&PlWHrSexl_5#J_w~q?HtH*CcL@ux?Dft^ zo!WW-;Ea>IIfR5n&{s=aLjgYY1rnxg6J+6YQ zo5_DR4q$OoK<5MzfiXdGlz})mVl}@v^0Q+VSl#2jhSfb!qmBBpx(6p!eB@q-y*-fT z=~4X@t9v5gABGsmjlmm%w?w1hV<0@vTIEo2EXFK^9#B$<5~HI>MR>|jF;tcr!0~k) z6A5R5$;#bGZ6L;yUlaTW;w$-WfZzWmw#rWZ6kC6seCkZSi4?&@;D9lQodQWn3mMx$2bYb;t>NiEuCxNQze#rv02 zDw3obutNr$X4*Zliw1V3=Iwv6u+~(o*cSaCT zh=XVwZz@vW7VA~-A6 zq=~=>8FZV9-j-CM6#BGFq5HtB)xN6Ehopx?8IsCmx>PnCcH*Eto-}Y{w^Y70ZEO10 zDO)r2a|B((v^Y=p!!8y-NV2sIn|@v7|6EjDT{iUR;CoJk4qvCZub%rJ;l88bdysqq zVZirp@_o+8A(}bF82EbmR}8+M5p?t&&l>(i?}6@2O1UV?lYLk}M@wle$Ubb3Z2XkY zZ0y>`qqZ)4NaIJgPP?-4W7~PuPK}en7ZpXU0;i}+Fso@}yn zM_|^mE&-CIvUqRN>{Mj)& zT{3grq;sgJ;8uPW<}SR`tJLucW@UU3AYz3CGc*<6pT3|o0I7;sfD(iY(6bMp&YN`9 zXK0t`rQ*>+O|Oo-NBg|`D>I|D(U2`MTP|(xDT%T0(sJ9wFJ$OpRiI(!3$QBS3;}-X z8fId206zttZ>M57eIs%t9&qes+h_$Y{eA6GjElPi-(0l--dOG6bQ6F5Fjx`sKSkiJ z41_Z_jD^c~vJ*+$u|Lu4`*vbuG3Yq_c1RF4IgUuKhO zWv;+`VILf>Pf*uYw-5qpWc6Ocox6Q1+zKDBO{gylk1S3WDqGNh z>A8oUhC52BO0$>DD=a1$nOaC7OX

drAu=F9`Lso7qTqpiU}ll&qeel{Ey*zxHsC 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 RN0u-Dz2v}44*Z`v@LvO^sLucZ literal 0 HcmV?d00001 diff --git a/release/boot.rom b/release/boot.rom new file mode 100644 index 0000000000000000000000000000000000000000..ea66af5bec097c13a44f536dcdf453c9d05254e6 GIT binary patch literal 131072 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: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 literal 0 HcmV?d00001 diff --git a/scc.v b/scc.v new file mode 100644 index 0000000..92a0323 --- /dev/null +++ b/scc.v @@ -0,0 +1,587 @@ +`timescale 1ns / 100ps + +/* + * Zilog 8530 SCC module for minimigmac. + * + * Located on high data bus, but writes are done at odd addresses as + * LDS is used as WR signals or something like that on a Mac Plus. + * + * We don't care here and just ignore which side was used. + * + * NOTE: We don't implement the 85C30 or ESCC additions such as WR7' + * for now, it's all very simplified + */ + +module scc +( + input clk, + input cep, + input cen, + + input reset_hw, + + /* Bus interface. 2-bit address, to be wired + * appropriately upstream (to A1..A2). + */ + input cs, + input we, + input [1:0] rs, /* [1] = data(1)/ctl [0] = a_side(1)/b_side */ + input [7:0] wdata, + output [7:0] rdata, + output _irq, + + /* A single serial port on Minimig */ + input rxd, + output txd, + input cts, /* normally wired to device DTR output + * on Mac cables. That same line is also + * connected to the TRxC input of the SCC + * to do fast clocking but we don't do that + * here + */ + output rts, /* on a real mac this activates line + * drivers when low */ + + /* DCD for both ports are hijacked by mouse interface */ + input dcd_a, /* We don't synchronize those inputs */ + input dcd_b, + + /* Write request */ + output wreq +); + + /* Register access is semi-insane */ + reg [3:0] rindex; + reg [3:0] rindex_latch; + wire wreg_a; + wire wreg_b; + + /* Resets via WR9, one clk pulses */ + wire reset_a; + wire reset_b; + wire reset; + + /* Data registers */ + reg [7:0] data_a = 0; + reg [7:0] data_b = 0; + + /* Read registers */ + wire [7:0] rr0_a; + wire [7:0] rr0_b; + wire [7:0] rr1_a; + wire [7:0] rr1_b; + wire [7:0] rr2_b; + wire [7:0] rr3_a; + wire [7:0] rr10_a; + wire [7:0] rr10_b; + wire [7:0] rr15_a; + wire [7:0] rr15_b; + + /* Write registers. Only some are implemented, + * some result in actions on write and don't + * store anything + */ + reg [7:0] wr1_a; + reg [7:0] wr1_b; + reg [7:0] wr2; + reg [7:0] wr5_a; + reg [7:0] wr5_b; + reg [7:0] wr6_a; + reg [7:0] wr6_b; + reg [7:0] wr8_a; + reg [7:0] wr8_b; + reg [5:0] wr9; + reg [7:0] wr10_a; + reg [7:0] wr10_b; + reg [7:0] wr12_a; + reg [7:0] wr12_b; + reg [7:0] wr13_a; + reg [7:0] wr13_b; + reg [7:0] wr14_a; + reg [7:0] wr14_b; + reg [7:0] wr15_a; + reg [7:0] wr15_b; + + /* Status latches */ + reg latch_open_a; + reg latch_open_b; + reg dcd_latch_a; + reg dcd_latch_b; + wire dcd_ip_a; + wire dcd_ip_b; + wire do_latch_a; + wire do_latch_b; + wire do_extreset_a; + wire do_extreset_b; + + /* IRQ stuff */ + wire rx_irq_pend_a; + wire rx_irq_pend_b; + wire tx_irq_pend_a; + wire tx_irq_pend_b; + wire ex_irq_pend_a; + wire ex_irq_pend_b; + reg ex_irq_ip_a; + reg ex_irq_ip_b; + wire [2:0] rr2_vec_stat; + + /* Register/Data access helpers */ + assign wreg_a = cs & we & (~rs[1]) & rs[0]; + assign wreg_b = cs & we & (~rs[1]) & ~rs[0]; + + // make sure rindex changes after the cpu cycle has ended so + // read data is still stable while cpu advances + always@(posedge clk) if(cen) rindex <= rindex_latch; + + /* Register index is set by a write to WR0 and reset + * after any subsequent write. We ignore the side + */ + always@(posedge clk or posedge reset) begin + if (reset) + rindex_latch <= 0; + else if (cen && cs && !rs[1]) begin + /* Default, reset index */ + rindex_latch <= 0; + + /* Write to WR0 */ + if (we && rindex == 0) begin + /* Get low index bits */ + rindex_latch[2:0] <= wdata[2:0]; + + /* Add point high */ + rindex_latch[3] <= (wdata[5:3] == 3'b001); + end + end + end + + /* Reset logic (write to WR9 cmd) + * + * Note about resets: Some bits are documented as unchanged/undefined on + * HW reset by the doc. We apply this to channel and soft resets, however + * we _do_ reset every bit on an external HW reset in this implementation + * to make the FPGA & synthesis tools happy. + */ + assign reset = ((wreg_a | wreg_b) & (rindex == 9) & (wdata[7:6] == 2'b11)) | reset_hw; + assign reset_a = ((wreg_a | wreg_b) & (rindex == 9) & (wdata[7:6] == 2'b10)) | reset; + assign reset_b = ((wreg_a | wreg_b) & (rindex == 9) & (wdata[7:6] == 2'b01)) | reset; + + /* WR1 + * Reset: bit 5 and 2 unchanged */ + always@(posedge clk or posedge reset_hw) begin + if (reset_hw) + wr1_a <= 0; + else if(cen) begin + if (reset_a) + wr1_a <= { 2'b00, wr1_a[5], 2'b00, wr1_a[2], 2'b00 }; + else if (wreg_a && rindex == 1) + wr1_a <= wdata; + end + end + always@(posedge clk or posedge reset_hw) begin + if (reset_hw) + wr1_b <= 0; + else if(cen) begin + if (reset_b) + wr1_b <= { 2'b00, wr1_b[5], 2'b00, wr1_b[2], 2'b00 }; + else if (wreg_b && rindex == 1) + wr1_b <= wdata; + end + end + + /* WR2 + * Reset: unchanged + */ + always@(posedge clk or posedge reset_hw) begin + if (reset_hw) + wr2 <= 0; + else if (cen && (wreg_a || wreg_b) && rindex == 2) + wr2 <= wdata; + end + + /* WR5 + * Reset: Bits 7,4,3,2,1 to 0 + */ + always@(posedge clk or posedge reset_hw) begin + if (reset_hw) + wr5_a <= 0; + else if(cen) begin + if (reset_a) + wr5_a <= { 1'b0, wr5_a[6:5], 4'b0000, wr5_a[0] }; + else if (wreg_a && rindex == 5) + wr5_a <= wdata; + end + end + always@(posedge clk or posedge reset_hw) begin + if (reset_hw) + wr5_b <= 0; + else if(cen) begin + if (reset_b) + wr5_b <= { 1'b0, wr5_b[6:5], 4'b0000, wr5_b[0] }; + else if (wreg_b && rindex == 5) + wr5_b <= wdata; + end + end + + /* WR9. Special: top bits are reset, handled separately, bottom + * bits are only reset by a hw reset + */ + always@(posedge clk or posedge reset_hw) begin + if (reset_hw) + wr9 <= 0; + else if (cen && (wreg_a || wreg_b) && rindex == 9) + wr9 <= wdata[5:0]; + end + + /* WR10 + * Reset: all 0, except chanel reset retains 6 and 5 + */ + always@(posedge clk or posedge reset) begin + if (reset) + wr10_a <= 0; + else if(cen) begin + if (reset_a) + wr10_a <= { 1'b0, wr10_a[6:5], 5'b00000 }; + else if (wreg_a && rindex == 10) + wr10_a <= wdata; + end + end + always@(posedge clk or posedge reset) begin + if (reset) + wr10_b <= 0; + else if(cen) begin + if (reset_b) + wr10_b <= { 1'b0, wr10_b[6:5], 5'b00000 }; + else if (wreg_b && rindex == 10) + wr10_b <= wdata; + end + end + + /* WR12 + * Reset: Unchanged + */ + always@(posedge clk or posedge reset_hw) begin + if (reset_hw) + wr12_a <= 0; + else if (cen && wreg_a && rindex == 12) + wr12_a <= wdata; + end + always@(posedge clk or posedge reset_hw) begin + if (reset_hw) + wr12_b <= 0; + else if (cen && wreg_b && rindex == 12) + wr12_b <= wdata; + end + + /* WR13 + * Reset: Unchanged + */ + always@(posedge clk or posedge reset_hw) begin + if (reset_hw) + wr13_a <= 0; + else if (cen && wreg_a && rindex == 13) + wr13_a <= wdata; + end + always@(posedge clk or posedge reset_hw) begin + if (reset_hw) + wr13_b <= 0; + else if (cen && wreg_b && rindex == 13) + wr13_b <= wdata; + end + + /* WR14 + * Reset: Full reset maintains top 2 bits, + * Chan reset also maitains bottom 2 bits, bit 4 also + * reset to a different value + */ + always@(posedge clk or posedge reset_hw) begin + if (reset_hw) + wr14_a <= 0; + else if(cen) begin + if (reset) + wr14_a <= { wr14_a[7:6], 6'b110000 }; + else if (reset_a) + wr14_a <= { wr14_a[7:6], 4'b1000, wr14_a[1:0] }; + else if (wreg_a && rindex == 14) + wr14_a <= wdata; + end + end + always@(posedge clk or posedge reset_hw) begin + if (reset_hw) + wr14_b <= 0; + else if(cen) begin + if (reset) + wr14_b <= { wr14_b[7:6], 6'b110000 }; + else if (reset_b) + wr14_b <= { wr14_b[7:6], 4'b1000, wr14_b[1:0] }; + else if (wreg_b && rindex == 14) + wr14_b <= wdata; + end + end + + /* WR15 */ + always@(posedge clk or posedge reset) begin + if (reset) begin + wr15_a <= 8'b11111000; + wr15_b <= 8'b11111000; + end else if (cen && rindex == 15) begin + if(wreg_a) wr15_a <= wdata; + if(wreg_b) wr15_b <= wdata; + end + end + + /* Read data mux */ + assign rdata = rs[1] && rs[0] ? data_a : + rs[1] ? data_b : + rindex == 0 && rs[0] ? rr0_a : + rindex == 0 ? rr0_b : + rindex == 1 && rs[0] ? rr1_a : + rindex == 1 ? rr1_b : + rindex == 2 && rs[0] ? wr2 : + rindex == 2 ? rr2_b : + rindex == 3 && rs[0] ? rr3_a : + rindex == 3 ? 8'h00 : + rindex == 4 && rs[0] ? rr0_a : + rindex == 4 ? rr0_b : + rindex == 5 && rs[0] ? rr1_a : + rindex == 5 ? rr1_b : + rindex == 6 && rs[0] ? wr2 : + rindex == 6 ? rr2_b : + rindex == 7 && rs[0] ? rr3_a : + rindex == 7 ? 8'h00 : + + rindex == 8 && rs[0] ? data_a : + rindex == 8 ? data_b : + rindex == 9 && rs[0] ? wr13_a : + rindex == 9 ? wr13_b : + rindex == 10 && rs[0] ? rr10_a : + rindex == 10 ? rr10_b : + rindex == 11 && rs[0] ? rr15_a : + rindex == 11 ? rr15_b : + rindex == 12 && rs[0] ? wr12_a : + rindex == 12 ? wr12_b : + rindex == 13 && rs[0] ? wr13_a : + rindex == 13 ? wr13_b : + rindex == 14 && rs[0] ? rr10_a : + rindex == 14 ? rr10_b : + rindex == 15 && rs[0] ? rr15_a : + rindex == 15 ? rr15_b : 8'hff; + + /* RR0 */ + assign rr0_a = { 1'b0, /* Break */ + 1'b1, /* Tx Underrun/EOM */ + 1'b0, /* CTS */ + 1'b0, /* Sync/Hunt */ + wr15_a[3] ? dcd_latch_a : dcd_a, /* DCD */ + 1'b1, /* Tx Empty */ + 1'b0, /* Zero Count */ + 1'b0 /* Rx Available */ + }; + assign rr0_b = { 1'b0, /* Break */ + 1'b1, /* Tx Underrun/EOM */ + 1'b0, /* CTS */ + 1'b0, /* Sync/Hunt */ + wr15_b[3] ? dcd_latch_b : dcd_b, /* DCD */ + 1'b1, /* Tx Empty */ + 1'b0, /* Zero Count */ + 1'b0 /* Rx Available */ + }; + + /* RR1 */ + assign rr1_a = { 1'b0, /* End of frame */ + 1'b0, /* CRC/Framing error */ + 1'b0, /* Rx Overrun error */ + 1'b0, /* Parity error */ + 1'b0, /* Residue code 0 */ + 1'b1, /* Residue code 1 */ + 1'b1, /* Residue code 2 */ + 1'b1 /* All sent */ + }; + + assign rr1_b = { 1'b0, /* End of frame */ + 1'b0, /* CRC/Framing error */ + 1'b0, /* Rx Overrun error */ + 1'b0, /* Parity error */ + 1'b0, /* Residue code 0 */ + 1'b1, /* Residue code 1 */ + 1'b1, /* Residue code 2 */ + 1'b1 /* All sent */ + }; + + /* RR2 (Chan B only, A is just WR2) */ + assign rr2_b = { wr2[7], + wr9[4] ? rr2_vec_stat[0] : wr2[6], + wr9[4] ? rr2_vec_stat[1] : wr2[5], + wr9[4] ? rr2_vec_stat[2] : wr2[4], + wr9[4] ? wr2[3] : rr2_vec_stat[2], + wr9[4] ? wr2[2] : rr2_vec_stat[1], + wr9[4] ? wr2[1] : rr2_vec_stat[0], + wr2[0] + }; + + + /* RR3 (Chan A only) */ + assign rr3_a = { 2'b0, + rx_irq_pend_a, /* Rx interrupt pending */ + tx_irq_pend_a, /* Tx interrupt pending */ + ex_irq_pend_a, /* Status/Ext interrupt pending */ + rx_irq_pend_b, + tx_irq_pend_b, + ex_irq_pend_b + }; + + /* RR10 */ + assign rr10_a = { 1'b0, /* One clock missing */ + 1'b0, /* Two clocks missing */ + 1'b0, + 1'b0, /* Loop sending */ + 1'b0, + 1'b0, + 1'b0, /* On Loop */ + 1'b0 + }; + assign rr10_b = { 1'b0, /* One clock missing */ + 1'b0, /* Two clocks missing */ + 1'b0, + 1'b0, /* Loop sending */ + 1'b0, + 1'b0, + 1'b0, /* On Loop */ + 1'b0 + }; + + /* RR15 */ + assign rr15_a = { wr15_a[7], + wr15_a[6], + wr15_a[5], + wr15_a[4], + wr15_a[3], + 1'b0, + wr15_a[1], + 1'b0 + }; + + assign rr15_b = { wr15_b[7], + wr15_b[6], + wr15_b[5], + wr15_b[4], + wr15_b[3], + 1'b0, + wr15_b[1], + 1'b0 + }; + + /* Interrupts. Simplified for now + * + * Need to add latches. Tx irq is latched when buffer goes from full->empty, + * it's not a permanent state. For now keep it clear. Will have to fix that. + */ + assign rx_irq_pend_a = 0; + assign tx_irq_pend_a = 0 /*& wr1_a[1]*/; /* Tx always empty for now */ + assign ex_irq_pend_a = ex_irq_ip_a; + assign rx_irq_pend_b = 0; + assign tx_irq_pend_b = 0 /*& wr1_b[1]*/; /* Tx always empty for now */ + assign ex_irq_pend_b = ex_irq_ip_b; + + assign _irq = ~(wr9[3] & (rx_irq_pend_a | + rx_irq_pend_b | + tx_irq_pend_a | + tx_irq_pend_b | + ex_irq_pend_a | + ex_irq_pend_b)); + + /* XXX Verify that... also missing special receive condition */ + assign rr2_vec_stat = rx_irq_pend_a ? 3'b110 : + tx_irq_pend_a ? 3'b100 : + ex_irq_pend_a ? 3'b101 : + rx_irq_pend_b ? 3'b010 : + tx_irq_pend_b ? 3'b000 : + ex_irq_pend_b ? 3'b001 : 3'b011; + + /* External/Status interrupt & latch logic */ + assign do_extreset_a = wreg_a & (rindex == 0) & (wdata[5:3] == 3'b010); + assign do_extreset_b = wreg_b & (rindex == 0) & (wdata[5:3] == 3'b010); + + /* Internal IP bit set if latch different from source and + * corresponding interrupt is enabled in WR15 + */ + assign dcd_ip_a = (dcd_a != dcd_latch_a) & wr15_a[3]; + assign dcd_ip_b = (dcd_b != dcd_latch_b) & wr15_b[3]; + + /* Latches close when an enabled IP bit is set and latches + * are currently open + */ + assign do_latch_a = latch_open_a & (dcd_ip_a /* | cts... */); + assign do_latch_b = latch_open_b & (dcd_ip_b /* | cts... */); + + /* "Master" interrupt, set when latch close & WR1[0] is set */ + always@(posedge clk or posedge reset) begin + if (reset) + ex_irq_ip_a <= 0; + else if(cep) begin + if (do_extreset_a) + ex_irq_ip_a <= 0; + else if (do_latch_a && wr1_a[0]) + ex_irq_ip_a <= 1; + end + end + always@(posedge clk or posedge reset) begin + if (reset) + ex_irq_ip_b <= 0; + else if(cep) begin + if (do_extreset_b) + ex_irq_ip_b <= 0; + else if (do_latch_b && wr1_b[0]) + ex_irq_ip_b <= 1; + end + end + + /* Latch open/close control */ + always@(posedge clk or posedge reset) begin + if (reset) + latch_open_a <= 1; + else if(cep) begin + if (do_extreset_a) + latch_open_a <= 1; + else if (do_latch_a) + latch_open_a <= 0; + end + end + always@(posedge clk or posedge reset) begin + if (reset) + latch_open_b <= 1; + else if(cep) begin + if (do_extreset_b) + latch_open_b <= 1; + else if (do_latch_b) + latch_open_b <= 0; + end + end + + /* Latches proper */ + always@(posedge clk or posedge reset) begin + if (reset) begin + dcd_latch_a <= 0; + /* cts ... */ + end else if(cep) begin + if (do_latch_a) + dcd_latch_a <= dcd_a; + /* cts ... */ + end + end + always@(posedge clk or posedge reset) begin + if (reset) begin + dcd_latch_b <= 0; + /* cts ... */ + end else if(cep) begin + if (do_latch_b) + dcd_latch_b <= dcd_b; + /* cts ... */ + end + end + + /* NYI */ + assign txd = 1; + assign rts = 1; + + assign wreq = 1; +endmodule diff --git a/scsi.v b/scsi.v new file mode 100644 index 0000000..5fd494d --- /dev/null +++ b/scsi.v @@ -0,0 +1,340 @@ +/* verilator lint_off UNUSED */ +/* verilator lint_off SYNCASYNCNET */ + +// scsi.v +// implements a target only scsi device + +module scsi +( + input clk, + + // scsi interface + input rst, // bus reset from initiator + input sel, + input atn, // initiator requests to send a message + output bsy, // target holds bus + + output msg, + output cd, + output io, + + output req, + input ack, // initiator acknowledges a request + + input [7:0] din, // data from initiator to target + output [7:0] dout, // data from target to initiator + + // interface to io controller + output [31:0] io_lba, + output reg io_rd, + output reg io_wr, + input io_ack, + + input [8:0] sd_buff_addr, + input [7:0] sd_buff_dout, + output reg [7:0] sd_buff_din, + input sd_buff_wr +); + + +// SCSI device id +parameter ID = 0; + +`define PHASE_IDLE 3'd0 +`define PHASE_CMD_IN 3'd1 +`define PHASE_DATA_OUT 3'd2 +`define PHASE_DATA_IN 3'd3 +`define PHASE_STATUS_OUT 3'd4 +`define PHASE_MESSAGE_OUT 3'd5 +reg [2:0] phase; + +// ---------------- buffer read engine ----------------------- +// the buffer itself. Can hold one sector +reg [7:0] buffer_out [512]; +always @(posedge clk) sd_buff_din <= buffer_out[sd_buff_addr]; + +// ---------------- buffer write engine ---------------------- +// the buffer itself. Can hold one sector +reg [7:0] buffer_in [512]; +always @(posedge clk) if(sd_buff_wr) buffer_in[sd_buff_addr] <= sd_buff_dout; + +// ----------------------------------------------------------- + +// status replies +reg [7:0] status; +`define STATUS_OK 8'h00 +`define STATUS_CHECK_CONDITION 8'h02 + +// message codes +`define MSG_CMD_COMPLETE 8'h00 + +// drive scsi signals according to phase +assign msg = (phase == `PHASE_MESSAGE_OUT); +assign cd = (phase == `PHASE_CMD_IN) || (phase == `PHASE_STATUS_OUT) || (phase == `PHASE_MESSAGE_OUT); +assign io = (phase == `PHASE_DATA_OUT) || (phase == `PHASE_STATUS_OUT) || (phase == `PHASE_MESSAGE_OUT); +assign req = (phase != `PHASE_IDLE) && !ack && !io_rd && !io_wr && !io_ack; +assign bsy = (phase != `PHASE_IDLE); + +assign dout = (phase == `PHASE_STATUS_OUT)?status: + (phase == `PHASE_MESSAGE_OUT)?`MSG_CMD_COMPLETE: + (phase == `PHASE_DATA_OUT)?cmd_dout: + 8'h00; + +// de-multiplex different data sources +wire [7:0] cmd_dout = + cmd_read?buffer_dout: + cmd_inquiry?inquiry_dout: + cmd_read_capacity?read_capacity_dout: + cmd_mode_sense?mode_sense_dout: + 8'h00; + +// output of inquiry command, identify as "SEAGATE ST225N" +wire [7:0] inquiry_dout = + (data_cnt == 32'd4 )?8'd32: // length + + (data_cnt == 32'd8 )?" ":(data_cnt == 32'd9 )?"S": + (data_cnt == 32'd10)?"E":(data_cnt == 32'd11)?"A": + (data_cnt == 32'd12)?"G":(data_cnt == 32'd13)?"A": + (data_cnt == 32'd14)?"T":(data_cnt == 32'd15)?"E": + (data_cnt == 32'd16)?" ":(data_cnt == 32'd17)?" ": + (data_cnt == 32'd18)?" ":(data_cnt == 32'd19)?" ": + (data_cnt == 32'd20)?" ":(data_cnt == 32'd21)?" ": + (data_cnt == 32'd22)?" ":(data_cnt == 32'd23)?" ": + (data_cnt == 32'd24)?" ":(data_cnt == 32'd25)?" ": + + (data_cnt == 32'd26)?"S":(data_cnt == 32'd27)?"T": + (data_cnt == 32'd28)?"2":(data_cnt == 32'd29)?"2": + (data_cnt == 32'd30)?"5":(data_cnt == 32'd31)?"N": + 8'h00; + +// output of read capacity command +wire [31:0] capacity = 32'd41056; // 40960 + 96 blocks = 20MB +wire [31:0] capacity_m1 = capacity - 32'd1; +wire [7:0] read_capacity_dout = + (data_cnt == 32'd0 )?capacity_m1[31:24]: + (data_cnt == 32'd1 )?capacity_m1[23:16]: + (data_cnt == 32'd2 )?capacity_m1[15:8]: + (data_cnt == 32'd3 )?capacity_m1[7:0]: + (data_cnt == 32'd6 )?8'd2: // 512 bytes per sector + 8'h00; + +wire [7:0] mode_sense_dout = + (data_cnt == 32'd3 )?8'd8: + (data_cnt == 32'd5 )?capacity[23:16]: + (data_cnt == 32'd6 )?capacity[15:8]: + (data_cnt == 32'd7 )?capacity[7:0]: + (data_cnt == 32'd10 )?8'd2: + 8'h00; + +// clock data out of buffer to allow for embedded ram +reg [7:0] buffer_dout; +always @(posedge clk) buffer_dout <= buffer_in[data_cnt]; + +// buffer to store incoming commands +reg [3:0] cmd_cnt; +reg [7:0] cmd [9:0]; + +/* ----------------------- request data from/to io controller ----------------------- */ + +// base address of current block. Subtract one when writing since the writing happens +// after a block has been transferred and data_cnt has thus already been increased by 512 +assign io_lba = lba + { 9'd0, data_cnt[31:9] } - + (cmd_write ? 32'd1 : 32'd0); + +wire req_rd = ((phase == `PHASE_DATA_OUT) && cmd_read && (data_cnt[8:0] == 0) && !data_complete); +wire req_wr = ((((phase == `PHASE_DATA_IN) && (data_cnt[8:0] == 0) && (data_cnt != 0)) || (phase == `PHASE_STATUS_OUT)) && cmd_write); +always @(posedge clk) begin + reg old_rd, old_wr; + + old_rd <= req_rd; + old_wr <= req_wr; + + if(io_ack) begin + io_rd <= 1'b0; + io_wr <= 1'b0; + end else begin + // generate an io_rd signal whenever the first byte of a 512 byte block is required and io_wr whenever + // the last byte of a 512 byte block has been revceived + if(~old_rd & req_rd) io_rd <= 1; + + // generate an io_wr signal whenever a 512 byte block has been received or when the status + // phase of a write command has been reached + if(~old_wr & req_wr) io_wr <= 1; + end +end + +reg stb_ack; +reg stb_adv; +always @(posedge clk) begin + reg old_ack; + + old_ack <= ack; + stb_ack <= (~old_ack & ack); + stb_adv <= stb_ack; +end + +// store data on rising edge of ack, ... +always @(posedge clk) begin + if(stb_ack) begin + if(phase == `PHASE_CMD_IN) cmd[cmd_cnt] <= din; + if(phase == `PHASE_DATA_IN) buffer_out[data_cnt] <= din; + end +end + +// ... advance counter on falling edge +always @(posedge clk) begin + if(phase == `PHASE_IDLE) cmd_cnt <= 4'd0; + else if(stb_adv && (phase == `PHASE_CMD_IN) && (cmd_cnt != 15)) cmd_cnt <= cmd_cnt + 4'd1; +end + +// count data bytes. don't increase counter while we are waiting for data from +// the io controller +reg [31:0] data_cnt; +reg data_complete; + +// For block transfers tlen contains the number of 512 bytes blocks to transfer. +// Most other commands have the bytes length stored in the transfer length field. +// And some have a fixed length idependent from any header field. +// The data transfer has finished once the data counter reaches this +// number. +wire [31:0] data_len = + cmd_read_capacity?32'd8: + cmd_read?{ 7'd0, tlen, 9'd0 }: // read command length is in 512 bytes blocks + cmd_write?{ 7'd0, tlen, 9'd0 }: // write command length is in 512 bytes blocks + { 16'd0, tlen }; // inquiry etc have length in bytes + +always @(posedge clk) begin + if((phase != `PHASE_DATA_OUT) && (phase != `PHASE_DATA_IN) && (phase != `PHASE_STATUS_OUT) && (phase != `PHASE_MESSAGE_OUT)) begin + data_cnt <= 0; + data_complete <= 0; + end else begin + if(stb_adv)begin + if(!data_complete) data_cnt <= data_cnt + 1'd1; + data_complete <= (data_len - 1'd1) == data_cnt; + end + end +end + +// check whether status byte has been sent +reg status_sent; +always @(posedge clk) begin + if(phase != `PHASE_STATUS_OUT) status_sent <= 0; + else if(stb_adv) status_sent <= 1; +end + +// check whether message byte has been sent +reg message_sent; +always @(posedge clk) begin + if(phase != `PHASE_MESSAGE_OUT) message_sent <= 0; + else if(stb_adv) message_sent <= 1; +end + +/* ----------------------- command decoding ------------------------------- */ + + +// parse commands +wire [7:0] op_code = cmd[0]; +wire [2:0] cmd_group = op_code[7:5]; + +// check if a complete command has been received +wire cmd_cpl = cmd6_cpl || cmd10_cpl; +wire cmd6_cpl = (cmd_group == 3'b000) && (cmd_cnt == 6); +wire cmd10_cpl = ((cmd_group == 3'b010) || (cmd_group == 3'b001)) && (cmd_cnt == 10); + +// https://en.wikipedia.org/wiki/SCSI_command +wire cmd_read = cmd_read6 || cmd_read10; +wire cmd_read6 = (op_code == 8'h08); +wire cmd_read10 = (op_code == 8'h28); +wire cmd_write = cmd_write6 || cmd_write10; +wire cmd_write6 = (op_code == 8'h0a); +wire cmd_write10 = (op_code == 8'h2a); +wire cmd_inquiry = (op_code == 8'h12); +wire cmd_format = (op_code == 8'h04); +wire cmd_mode_select = (op_code == 8'h15); +wire cmd_mode_sense = (op_code == 8'h1a); +wire cmd_test_unit_ready = (op_code == 8'h00); +wire cmd_read_capacity = (op_code == 8'h25); + +// valid command in buffer? TODO: check for valid command parameters +wire cmd_ok = cmd_read || cmd_write || cmd_inquiry || cmd_test_unit_ready || + cmd_read_capacity || cmd_mode_select || cmd_format || cmd_mode_sense; + +// latch parameters once command is complete +reg [31:0] lba; +reg [15:0] tlen; + +always @(posedge clk) begin + if(cmd_cpl && (phase == `PHASE_CMD_IN)) begin + lba <= cmd6_cpl?{11'd0, lba6}:lba10; + tlen <= cmd6_cpl?{7'd0, tlen6}:tlen10; + end +end + +// logical block address +wire [7:0] cmd1 = cmd[1]; +wire [20:0] lba6 = { cmd1[4:0], cmd[2], cmd[3] }; +wire [31:0] lba10 = { cmd[2], cmd[3], cmd[4], cmd[5] }; + +// transfer length +wire [8:0] tlen6 = (cmd[4] == 0)?9'd256:{1'b0,cmd[4]}; +wire [15:0] tlen10 = { cmd[7], cmd[8] }; + + +// the 5380 changes phase in the falling edge, thus we monitor it +// on the rising edge +always @(posedge clk) begin + if(rst) begin + phase <= `PHASE_IDLE; + end else begin + if(phase == `PHASE_IDLE) begin + if(sel && din[ID]) // own id on bus during selection? + phase <= `PHASE_CMD_IN; + end + + else if(phase == `PHASE_CMD_IN) begin + // check if a full command is in the buffer + if(cmd_cpl) begin + // is this a supported and valid command? + if(cmd_ok) begin + // yes, continue + status <= `STATUS_OK; + + // continue according to command + + // these commands return data + if(cmd_read || cmd_inquiry || cmd_read_capacity || cmd_mode_sense) phase <= `PHASE_DATA_OUT; + // these commands receive dataa + else if(cmd_write || cmd_mode_select) phase <= `PHASE_DATA_IN; + // and all other valid commands are just "ok" + else phase <= `PHASE_STATUS_OUT; + end else begin + // no, report failure + status <= `STATUS_CHECK_CONDITION; + phase <= `PHASE_STATUS_OUT; + end + end + end + + else if(phase == `PHASE_DATA_OUT) begin + if(data_complete) phase <= `PHASE_STATUS_OUT; + end + + else if(phase == `PHASE_DATA_IN) begin + if(data_complete) phase <= `PHASE_STATUS_OUT; + end + + else if(phase == `PHASE_STATUS_OUT) begin + if(status_sent) phase <= `PHASE_MESSAGE_OUT; + end + + else if(phase == `PHASE_MESSAGE_OUT) begin + if(message_sent) phase <= `PHASE_IDLE; + end + + else + phase <= `PHASE_IDLE; // should never happen + end +end + + +endmodule diff --git a/sys/build_id.tcl b/sys/build_id.tcl new file mode 100644 index 0000000..7ef0665 --- /dev/null +++ b/sys/build_id.tcl @@ -0,0 +1,35 @@ +# ================================================================================ +# +# Build ID Verilog Module Script +# Jeff Wiencrot - 8/1/2011 +# +# Generates a Verilog module that contains a timestamp, +# from the current build. These values are available from the build_date, build_time, +# physical_address, and host_name output ports of the build_id module in the build_id.v +# Verilog source file. +# +# ================================================================================ + +proc generateBuildID_Verilog {} { + + # Get the timestamp (see: http://www.altera.com/support/examples/tcl/tcl-date-time-stamp.html) + set buildDate [ clock format [ clock seconds ] -format %y%m%d ] + set buildTime [ clock format [ clock seconds ] -format %H%M%S ] + + # Create a Verilog file for output + set outputFileName "build_id.v" + set outputFile [open $outputFileName "w"] + + # Output the Verilog source + puts $outputFile "`define BUILD_DATE \"$buildDate\"" + puts $outputFile "`define BUILD_TIME \"$buildTime\"" + close $outputFile + + # Send confirmation message to the Messages window + post_message "Generated build identification Verilog module: [pwd]/$outputFileName" + post_message "Date: $buildDate" + post_message "Time: $buildTime" +} + +# Comment out this line to prevent the process from automatically executing when the file is sourced: +generateBuildID_Verilog \ No newline at end of file diff --git a/sys/ddram.sv b/sys/ddram.sv new file mode 100644 index 0000000..139447d --- /dev/null +++ b/sys/ddram.sv @@ -0,0 +1,153 @@ +// +// ddram.v +// +// DE10-nano DDR3 memory interface +// +// Copyright (c) 2017 Sorgelig +// +// +// This source file 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 3 of the License, or +// (at your option) any later version. +// +// This source file 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, see . +// +// ------------------------------------------ +// + +module ddram +( + input RESET, + input 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, + + input wb_clk, // chipset clock to which sdram state machine is synchonized + input [31:0] wb_dat_i, // data input from chipset/cpu + output reg [31:0] wb_dat_o, // data output to chipset/cpu + input [27:0] wb_adr, // lower 2 bits are ignored. + input [3:0] wb_sel, // + input [2:0] wb_cti, // cycle type. + input wb_stb, // + input wb_cyc, // cpu/chipset requests cycle + input wb_we, // cpu/chipset requests write + output reg wb_ack +); + +assign DDRAM_BURSTCNT = burst; +assign DDRAM_BE = ({wb_sel&{4{wb_adr[2]}},wb_sel&{4{~wb_adr[2]}}}) | {8{ram_read}}; +assign DDRAM_ADDR = {4'b0011, wb_adr[27:3]}; // RAM at 0x30000000 +assign DDRAM_DIN = {wb_dat_i,wb_dat_i}; +assign DDRAM_RD = ram_read; +assign DDRAM_WE = ram_write; + +reg [31:0] ram_q[4]; +reg ram_read; +reg ram_write; + +reg op_req = 0, op_ack = 0; +reg op_we; + +always @(posedge DDRAM_CLK) +begin + reg state = 0; + reg opr; + reg [7:0] c; + + opr <= op_req; + + if(RESET) + begin + state <= 0; + ram_write <= 0; + ram_read <= 0; + end + else + if(!DDRAM_BUSY) + begin + ram_write <= 0; + ram_read <= 0; + + case(state) + 0: if(op_ack != opr) begin + ram_write <= op_we; + ram_read <= ~op_we; + state <= 1; + c <= 1; + end + 1: if(op_we) + begin + op_ack <= opr; + state <= 0; + end + else + if(DDRAM_DOUT_READY) begin + if(c[1]) {ram_q[3], ram_q[2]} <= DDRAM_DOUT; + else {ram_q[1], ram_q[0]} <= DDRAM_DOUT; + + c <= c + 1'd1; + if(c >= burst) begin + state <= 0; + op_ack <= opr; + end + end + endcase + end +end + +reg [7:0] burst; +always @(negedge wb_clk) begin + reg ack = 0; + reg state = 0; + reg [1:0] sz; + reg [1:0] cnt; + + ack <= op_ack; + + if(RESET) begin + state <= 0; + wb_ack <= 0; + end + else + case(state) + 0: begin + wb_ack <= 0; + if(~wb_ack & wb_stb & wb_cyc) begin + op_we <= wb_we; + sz <= 0; + burst <= 1; + if((wb_cti == 2) && ~wb_we) begin + sz <= 3; + burst <= 2; + end + cnt <= wb_adr[2]; + op_req <= ~op_req; + state <= 1; + end + end + 1: if(ack == op_req) + begin + wb_ack <= 1; + if(~op_we) wb_dat_o <= ram_q[cnt]; + cnt <= cnt + 1'd1; + if(cnt >= sz) state <= 0; + end + endcase +end + +endmodule diff --git a/sys/hdmi_config.sv b/sys/hdmi_config.sv new file mode 100644 index 0000000..dbc0dfd --- /dev/null +++ b/sys/hdmi_config.sv @@ -0,0 +1,265 @@ + +module hdmi_config +( + // Host Side + input iCLK, + input iRST_N, + + // 0 - 480i + // 1 - 480p + // 2 - 576i + // 3 - 576p + // 4 - 720p + // 5-7 - reserved + input [2:0] iRES, + + // 0 - 4:3 + // 1 - 16:9 + input iAR, + + input audio_48k, + + // I2C Side + output I2C_SCL, + inout I2C_SDA +); + +// Internal Registers/Wires +reg mI2C_GO = 0; +wire mI2C_END; +wire mI2C_ACK; +reg [15:0] LUT_DATA; +reg [7:0] LUT_INDEX = 0; + +I2C_Controller #(50_000_000, 400_000) i2c_av +( + .CLK(iCLK), + + .I2C_SCL(I2C_SCL), // I2C CLOCK + .I2C_SDA(I2C_SDA), // I2C DATA + + .I2C_DATA({8'h72,init_data[LUT_INDEX]}), // DATA:[SLAVE_ADDR,SUB_ADDR,DATA]. 0x72 is the Slave Address of the ADV7513 chip! + .START(mI2C_GO), // START transfer + .END(mI2C_END), // END transfer + .ACK(mI2C_ACK) // ACK +); + +////////////////////// Config Control //////////////////////////// +always@(posedge iCLK or negedge iRST_N) begin + reg [1:0] mSetup_ST = 0; + + if(!iRST_N) begin + LUT_INDEX <= 0; + mSetup_ST <= 0; + mI2C_GO <= 0; + end else begin + if(init_data[LUT_INDEX] != 16'hFFFF) begin + case(mSetup_ST) + 0: begin + mI2C_GO <= 1; + mSetup_ST <= 1; + end + 1: if(~mI2C_END) mSetup_ST <= 2; + 2: begin + mI2C_GO <= 0; + if(mI2C_END) begin + mSetup_ST <= 0; + if(!mI2C_ACK) LUT_INDEX <= LUT_INDEX + 8'd1; + end + end + endcase + end + end +end + +wire [15:0] res480i[6] = '{'h35_1D, 'h36_92, 'h37_05, 'h38_A0, 'h39_0F, 'h3A_00}; +wire [15:0] res480p[6] = '{'h35_1F, 'h36_E8, 'h37_05, 'h38_A0, 'h39_1E, 'h3A_00}; +wire [15:0] res576i[6] = '{'h35_20, 'h36_D6, 'h37_05, 'h38_A0, 'h39_12, 'h3A_00}; +wire [15:0] res576p[6] = '{'h35_20, 'h36_EC, 'h37_05, 'h38_A0, 'h39_24, 'h3A_00}; +wire [15:0] res720p[6] = '{'h35_40, 'h36_D9, 'h37_0A, 'h38_00, 'h39_2D, 'h3A_00}; + +reg [15:0] resVar[6]; +always_comb begin + case(iRES) + 0: resVar <= res480i; + 1: resVar <= res480p; + 2: resVar <= res576i; + 3: resVar <= res576p; + 4: resVar <= res720p; + default: resVar <= res720p; + endcase +end + + +//////////////////////////////////////////////////////////////////// +///////////////////// Config Data LUT ////////////////////////// + +wire [15:0] init_data[58] = +'{ + 16'h4110, // Power Down control + 16'h9803, // ADI required Write. + 16'h9A70, // ADI required Write. + 16'h9C30, // ADI required Write. + {8'h9D, 8'b0110_0001}, // [7:4] must be b0110!. + // [3:2] b00 = Input clock not divided. b01 = Clk divided by 2. b10 = Clk divided by 4. b11 = invalid! + // [1:0] must be b01! + 16'hA2A4, // ADI required Write. + 16'hA3A4, // ADI required Write. + 16'hE0D0, // ADI required Write. + + + resVar[0], + resVar[1], + resVar[2], + resVar[3], + resVar[4], + resVar[5], + + {8'h16, 8'b0011_1000}, // Output Format 444 [7]=0. + // [6] must be 0! + // Colour Depth for Input Video data [5:4] b11 = 8-bit. + // Input Style [3:2] b10 = Style 1 (ignored when using 444 input). + // DDR Input Edge falling [1]=0 (not using DDR atm). + // Output Colour Space RGB [0]=0. + +// {8'h16, 8'b1011_0101}, // Output Format 422 [7]=1. + // [6] must be 0! + // Colour Depth for Input Video data [5:4] b11 = 8-bit. + // Input Style [3:2] b01 = Style 2. + // DDR Input Edge falling [1]=0 (not using DDR atm). + // Output Colour Space YPrPb [0]=1. + +// {8'h17, 8'b0110_0000}, // Aspect ratio 4:3 [1]=0. DE Generation DISabled [0]=0. + // Vsync polarity HIGH [6]=0, LOW [6]=1. + // Hsync polarity HIGH [5]=0, LOW [5]=1. + +// {8'h17, 8'b0110_0001}, // Aspect ratio 4:3 [1]=0. DE Generation ENabled [0]=1. + +// {8'h17, 8'b0110_0011}, // Aspect ratio 16:9 [1]=1. DE Generation ENabled [0]=1. + + {8'h17, 6'b011000, iAR, 1'b0}, // Aspect ratio 16:9 [1]=1, 4:3 [1]=0 + + {8'h18, 8'b0100_0110}, // CSC disabled [7]=0. + // CSC Scaling Factor [6:5] b10 = +/- 4.0, -16384 - 16380. + // CSC Equation 3 [4:0] b00110. + + +// {8'h3B, 8'b0000_1010}, // Pixel repetition [6:5] b00 AUTO. [4:3] b01 x2 mult of input clock. [2:1] b01 x2 pixel rep to send to HDMI Rx. + + {8'h3B, 8'b0000_0000}, // Pixel repetition [6:5] b00 AUTO. [4:3] b00 x1 mult of input clock. [2:1] b00 x1 pixel rep to send to HDMI Rx. + +// {8'h3B, 8'b0110_1010}, // Pixel repetition [6:5] b11 MANUAL. [4:3] b01 x2 mult of input clock. [2:1] b01 x2 pixel rep to send to HDMI Rx. + +// {8'h3C, 8'b0000_0110}, // VIC#6 480i-60, 2x clk, 4:3. +// {8'h3C, 8'b0000_0001}, // VIC#1 VGA (640x480), 2x clk, 4:3. + +// {8'h3C, 8'b0000_0010}, // VIC#2 480p (720x480), 2x clk, 4:3. + + 16'h4000, // General Control Packet Enable + + {8'h48, 8'b0000_1000}, // [6]=0 Normal bus order! + // [5] DDR Alignment. + // [4:3] b01 Data right justified (for YCbCr 422 input modes). + + 16'h49A8, // ADI required Write. + 16'h4C00, // ADI required Write. + + {8'h55, 8'b0001_0000}, // [7] must be 0!. Set RGB444 in AVinfo Frame [6:5], Set active format [4]. +// {8'h55, 8'b0101_0000}, // [7] must be 0!. Set YCbCr 444 in AVinfo Frame [6:5], Set active format [4]. +// {8'h55, 8'b0011_0001}, // [7] must be 0!. Set YCbCr 422 in AVinfo Frame [6:5]. + // AVI InfoFrame Valid [4]. + // Bar Info [3:2] b00 Bars invalid. b01 Bars vertical. b10 Bars horizontal. b11 Bars both. + // Scan Info [1:0] b00 (No data). b01 TV. b10 PC. b11 None. + +// {8'h94, 8'b1000_0000}, // [7]=1 HPD Interrupt ENabled. + + 16'h7301, + + 16'h9400, // HPD Interrupt disabled. + + 16'h9902, // ADI required Write. + 16'h9B18, // ADI required Write. + + 16'h9F00, // ADI required Write. + + {8'hA1, 8'b0100_0000}, // [6]=1 Monitor Sense Power Down DISabled. + + 16'hA408, // ADI required Write. + 16'hA504, // ADI required Write. + 16'hA600, // ADI required Write. + 16'hA700, // ADI required Write. + 16'hA800, // ADI required Write. + 16'hA900, // ADI required Write. + 16'hAA00, // ADI required Write. + 16'hAB40, // ADI required Write. + + {8'hAF, 8'b0001_0110}, // [7]=0 HDCP Disabled. + // [6:5] must be b00! + // [4]=1 Current frame IS HDCP encrypted!??? (HDCP disabled anyway?) + // [3:2] must be b01! + // [1]=1 HDMI Mode. + // [0] must be b0! + + 16'hB900, // ADI required Write. + + {8'hBA, 8'b0110_0000}, // [7:5] Input Clock delay... + // b000 = -1.2ns. + // b001 = -0.8ns. + // b010 = -0.4ns. + // b011 = No delay. + // b100 = 0.4ns. + // b101 = 0.8ns. + // b110 = 1.2ns. + // b111 = 1.6ns. + + 16'hBB00, // ADI required Write. + + {8'hD6, 8'b1100_0000}, // [7:6] HPD Control... + // 00 = HPD is from both HPD pin or CDC HPD + // 01 = HPD is from CDC HPD + // 10 = HPD is from HPD pin + // 11 = HPD is always high + + 16'hDE9C, // ADI required Write. + 16'hE460, // ADI required Write. + 16'hFA7D, // Nbr of times to search for good phase + + + // (Audio stuff on Programming Guide, Page 66)... + + {8'h0A, 8'b0000_0000}, // [6:4] Audio Select. b000 = I2S. + // [3:2] Audio Mode. (HBR stuff, leave at 00!). + + {8'h0B, 8'b0000_1110}, // + + {8'h0C, 8'b0000_0100}, // [7] 0 = Use sampling rate from I2S stream. 1 = Use samp rate from I2C Register. + // [6] 0 = Use Channel Status bits from stream. 1 = Use Channel Status bits from I2C register. + // [2] 1 = I2S0 Enable. + // [1:0] I2S Format: 00 = Standard. 01 = Right Justified. 10 = Left Justified. 11 = AES. + + {8'h0D, 8'b0001_0000}, // [4:0] I2S Bit (Word) Width for Right-Justified. + {8'h14, 8'b0000_0010}, // [3:0] Audio Word Length. b0010 = 16 bits. + {8'h15, ~audio_48k, 7'b010_0000}, // I2S Sampling Rate [7:4]. b0000 = (44.1KHz). b0010 = 48KHz. + // Input ID [3:1] b000 (0) = 24-bit RGB 444 or YCrCb 444 with Separate Syncs. + +// {8'h15, 8'b0010_0001}, // I2S Sampling Rate [7:4]. b0000 = (44.1KHz). b0010 = 48KHz. + // Input ID [3:0] b0001 (1) = 16, 20, 24 bit YCbCr 4:2:2 with Separate Syncs. + +// {8'h15, 8'b0010_0011}, // I2S Sampling Rate [7:4]. b0000 = (44.1KHz). b0010 = 48KHz. + // Input ID [3:0] b0011 (3) = 16, 20, 24 bit YCbCr 4:2:2 (2x Pixel Clock, with Separate Syncs). + + // Audio Clock Config + 16'h0100, // + audio_48k ? 16'h0218 : 16'h0230, // Set N Value 12288/6144 + 16'h0300, // + + 16'h0701, // + 16'h0822, // Set CTS Value 74250 + 16'h090A, // + + 16'hFFFF // END +}; + +//////////////////////////////////////////////////////////////////// + +endmodule \ No newline at end of file diff --git a/sys/hps_io.v b/sys/hps_io.v new file mode 100644 index 0000000..40b5ef2 --- /dev/null +++ b/sys/hps_io.v @@ -0,0 +1,642 @@ +// +// hps_io.v +// +// mist_io-like module for the Terasic DE10 board +// +// Copyright (c) 2014 Till Harbaum +// Copyright (c) 2017 Sorgelig (port to DE10-nano) +// +// This source file 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 3 of the License, or +// (at your option) any later version. +// +// This source file 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, see . +// +/////////////////////////////////////////////////////////////////////// + +// +// Use buffer to access SD card. It's time-critical part. +// +// for synchronous projects default value for PS2DIV is fine for any frequency of system clock. +// clk_ps2 = CLK_SYS/(PS2DIV*2) +// + +// WIDE=1 for 16 bit file I/O +// VDNUM 1-4 +module hps_io #(parameter STRLEN=0, PS2DIV=2000, WIDE=0, VDNUM=1, PS2WE=0) +( + input clk_sys, + inout [43:0] HPS_BUS, + + // parameter STRLEN and the actual length of conf_str have to match + input [(8*STRLEN)-1:0] conf_str, + + output reg [15:0] joystick_0, + output reg [15:0] joystick_1, + output reg [15:0] joystick_analog_0, + output reg [15:0] joystick_analog_1, + + output [1:0] buttons, + output forced_scandoubler, + + output reg [31:0] status, + + // SD config + output reg [VD:0] img_mounted, // signaling that new image has been mounted + output reg img_readonly, // mounted as read only. valid only for active bit in img_mounted + output reg [63:0] img_size, // size of image in bytes. valid only for active bit in img_mounted + + // SD block level access + input [31:0] sd_lba, + input [VD:0] sd_rd, // only single sd_rd can be active at any given time + input [VD:0] sd_wr, // only single sd_wr can be active at any given time + output reg sd_ack, + + // do not use in new projects. + // CID and CSD are fake except CSD image size field. + input sd_conf, + output reg sd_ack_conf, + + // SD byte level access. Signals for 2-PORT altsyncram. + output reg [AW:0] sd_buff_addr, + output reg [DW:0] sd_buff_dout, + input [DW:0] sd_buff_din, + output reg sd_buff_wr, + + // ARM -> FPGA download + output reg ioctl_download = 0, // signal indicating an active download + output reg [7:0] ioctl_index, // menu index used to upload the file + output reg ioctl_wr, + output reg [23:0] ioctl_addr, // in WIDE mode address will be incremented by 2 + output reg [15:0] ioctl_dout, + input ioctl_wait, + + // RTC MSM6242B layout + output reg [63:0] RTC, + + // ps2 keyboard emulation + output ps2_kbd_clk_out, + output ps2_kbd_data_out, + input ps2_kbd_clk_in, + input ps2_kbd_data_in, + + input [2:0] ps2_kbd_led_status, + input [2:0] ps2_kbd_led_use, + + output ps2_mouse_clk_out, + output ps2_mouse_data_out, + input ps2_mouse_clk_in, + input ps2_mouse_data_in, + + // ps2 alternative interface. + output reg [64:0] ps2_key = 0, // up to 8 bytes per key (pause) + output reg [24:0] ps2_mouse = 0 +); + +localparam DW = (WIDE) ? 15 : 7; +localparam AW = (WIDE) ? 7 : 8; +localparam VD = VDNUM-1; + +wire io_wait = ioctl_wait; +wire io_enable= |HPS_BUS[35:34]; +wire io_strobe= HPS_BUS[33]; +wire io_wide = (WIDE) ? 1'b1 : 1'b0; +wire [15:0] io_din = HPS_BUS[31:16]; +reg [15:0] io_dout; + +assign HPS_BUS[37] = io_wait; +assign HPS_BUS[36] = clk_sys; +assign HPS_BUS[32] = io_wide; +assign HPS_BUS[15:0] = io_dout; + +reg [7:0] cfg; +assign buttons = cfg[1:0]; +//cfg[2] - vga_scaler handled in sys_top +//cfg[3] - csync handled in sys_top +assign forced_scandoubler = cfg[4]; +//cfg[5] - ypbpr handled in sys_top + +// command byte read by the io controller +wire [15:0] sd_cmd = +{ + 2'b00, + (VDNUM>=4) ? sd_wr[3] : 1'b0, + (VDNUM>=3) ? sd_wr[2] : 1'b0, + (VDNUM>=2) ? sd_wr[1] : 1'b0, + + (VDNUM>=4) ? sd_rd[3] : 1'b0, + (VDNUM>=3) ? sd_rd[2] : 1'b0, + (VDNUM>=2) ? sd_rd[1] : 1'b0, + + 4'h5, sd_conf, 1'b1, + sd_wr[0], + sd_rd[0] +}; + +///////////////// calc video parameters ////////////////// + +wire clk_100 = HPS_BUS[43]; +wire clk_vid = HPS_BUS[42]; +wire ce_pix = HPS_BUS[41]; +wire de = HPS_BUS[40]; +wire hs = HPS_BUS[39]; +wire vs = HPS_BUS[38]; + +reg [31:0] vid_hcnt = 0; +reg [31:0] vid_vcnt = 0; +reg [7:0] vid_nres = 0; +integer hcnt; + +always @(posedge clk_vid) begin + integer vcnt; + reg old_vs= 0, old_de = 0; + reg calch = 0; + + if(ce_pix) begin + old_vs <= vs; + old_de <= de; + + if(~vs & ~old_de & de) vcnt <= vcnt + 1; + if(calch & de) hcnt <= hcnt + 1; + if(old_de & ~de) calch <= 0; + + if(old_vs & ~vs) begin + if(hcnt && vcnt) begin + if(vid_hcnt != hcnt || vid_vcnt != vcnt) vid_nres <= vid_nres + 1'd1; + vid_hcnt <= hcnt; + vid_vcnt <= vcnt; + end + vcnt <= 0; + hcnt <= 0; + calch <= 1; + end + end +end + +reg [31:0] vid_htime = 0; +reg [31:0] vid_vtime = 0; +reg [31:0] vid_pix = 0; + +always @(posedge clk_100) begin + integer vtime, htime, hcnt; + reg old_vs, old_hs, old_vs2, old_hs2, old_de, old_de2; + reg calch = 0; + + old_vs <= vs; + old_hs <= hs; + + old_vs2 <= old_vs; + old_hs2 <= old_hs; + + vtime <= vtime + 1'd1; + htime <= htime + 1'd1; + + if(~old_vs2 & old_vs) begin + vid_pix <= hcnt; + vid_vtime <= vtime; + vtime <= 0; + hcnt <= 0; + end + + if(old_vs2 & ~old_vs) calch <= 1; + + if(~old_hs2 & old_hs) begin + vid_htime <= htime; + htime <= 0; + end + + old_de <= de; + old_de2 <= old_de; + + if(calch & old_de) hcnt <= hcnt + 1; + if(old_de2 & ~old_de) calch <= 0; +end + +///////////////////////////////////////////////////////// + +always@(posedge clk_sys) begin + reg [15:0] cmd; + reg [9:0] byte_cnt; // counts bytes + reg [2:0] b_wr; + reg [2:0] stick_idx; + + sd_buff_wr <= b_wr[0]; + if(b_wr[2] && (~&sd_buff_addr)) sd_buff_addr <= sd_buff_addr + 1'b1; + b_wr <= (b_wr<<1); + + {kbd_rd,kbd_we,mouse_rd,mouse_we} <= 0; + + if(~io_enable) begin + if(cmd == 4 && !PS2WE) ps2_mouse[24] <= ~ps2_mouse[24]; + if(cmd == 5 && !PS2WE) ps2_key[64] <= ~ps2_key[64]; + cmd <= 0; + byte_cnt <= 0; + sd_ack <= 0; + sd_ack_conf <= 0; + io_dout <= 0; + end else begin + if(io_strobe) begin + + io_dout <= 0; + if(~&byte_cnt) byte_cnt <= byte_cnt + 1'd1; + + if(byte_cnt == 0) begin + cmd <= io_din; + + case(io_din) + 'h19: sd_ack_conf <= 1; + 'h17, + 'h18: sd_ack <= 1; + endcase + + sd_buff_addr <= 0; + img_mounted <= 0; + if(io_din == 5) ps2_key[63:0] <= 0; + end else begin + + case(cmd) + // buttons and switches + 'h01: cfg <= io_din[7:0]; + 'h02: joystick_0 <= io_din; + 'h03: joystick_1 <= io_din; + + // store incoming ps2 mouse bytes + 'h04: begin + mouse_data <= io_din[7:0]; + mouse_we <= 1; + if(!PS2WE) begin + case(byte_cnt) + 1: ps2_mouse[7:0] <= io_din[7:0]; + 2: ps2_mouse[15:8] <= io_din[7:0]; + 3: ps2_mouse[23:16] <= io_din[7:0]; + endcase + end + end + + // store incoming ps2 keyboard bytes + 'h05: begin + if(!PS2WE) ps2_key[63:0] <= {ps2_key[55:0], io_din[7:0]}; + kbd_data <= io_din[7:0]; + kbd_we <= 1; + end + + // reading config string + 'h14: begin + // returning a byte from string + if(byte_cnt < STRLEN + 1) io_dout[7:0] <= conf_str[(STRLEN - byte_cnt)<<3 +:8]; + end + + // reading sd card status + 'h16: begin + case(byte_cnt) + 1: io_dout <= sd_cmd; + 2: io_dout <= sd_lba[15:0]; + 3: io_dout <= sd_lba[31:16]; + endcase + end + + // send SD config IO -> FPGA + // flag that download begins + // sd card knows data is config if sd_dout_strobe is asserted + // with sd_ack still being inactive (low) + 'h19, + // send sector IO -> FPGA + // flag that download begins + 'h17: begin + sd_buff_dout <= io_din[DW:0]; + b_wr <= 1; + end + + // reading sd card write data + 'h18: begin + if(~&sd_buff_addr) sd_buff_addr <= sd_buff_addr + 1'b1; + io_dout <= sd_buff_din; + end + + // joystick analog + 'h1a: begin + // first byte is joystick index + if(byte_cnt == 1) stick_idx <= io_din[2:0]; + if(byte_cnt == 2) begin + if(stick_idx == 0) joystick_analog_0 <= io_din; + if(stick_idx == 1) joystick_analog_1 <= io_din; + end + end + + // notify image selection + 'h1c: begin + img_mounted <= io_din[VD:0] ? io_din[VD:0] : 1'b1; + img_readonly <= io_din[7]; + end + + // send image info + 'h1d: if(byte_cnt<5) img_size[{byte_cnt-1'b1, 4'b0000} +:16] <= io_din; + + // status, 32bit version + 'h1e: if(byte_cnt==1) status[15:0] <= io_din; + else if(byte_cnt==2) status[31:16] <= io_din; + + // reading keyboard LED status + 'h1f: io_dout <= {|PS2WE, 2'b01, ps2_kbd_led_status[2], ps2_kbd_led_use[2], ps2_kbd_led_status[1], ps2_kbd_led_use[1], ps2_kbd_led_status[0], ps2_kbd_led_use[0]}; + + // reading ps2 keyboard/mouse control + 'h21: begin + if(byte_cnt == 1) begin + io_dout <= kbd_data_host; + kbd_rd <= 1; + end + + if(byte_cnt == 2) begin + io_dout <= mouse_data_host; + mouse_rd <= 1; + end + end + //RTC + 'h22: RTC[(byte_cnt-6'd1)<<4 +:16] <= io_din; + + //Video res. + 'h23: begin + case(byte_cnt) + 1: io_dout <= vid_nres; + 2: io_dout <= vid_hcnt[15:0]; + 3: io_dout <= vid_hcnt[31:16]; + 4: io_dout <= vid_vcnt[15:0]; + 5: io_dout <= vid_vcnt[31:16]; + 6: io_dout <= vid_htime[15:0]; + 7: io_dout <= vid_htime[31:16]; + 8: io_dout <= vid_vtime[15:0]; + 9: io_dout <= vid_vtime[31:16]; + 10: io_dout <= vid_pix[15:0]; + 11: io_dout <= vid_pix[31:16]; + endcase + end + endcase + end + end + end +end + + +/////////////////////////////// PS2 /////////////////////////////// +reg clk_ps2; +always @(negedge clk_sys) begin + integer cnt; + cnt <= cnt + 1'd1; + if(cnt == PS2DIV) begin + clk_ps2 <= ~clk_ps2; + cnt <= 0; + end +end + +reg [7:0] kbd_data; +reg kbd_we; +wire [8:0] kbd_data_host; +reg kbd_rd; + +ps2_device keyboard +( + .clk_sys(clk_sys), + + .wdata(kbd_data), + .we(kbd_we), + + .ps2_clk(clk_ps2), + .ps2_clk_out(ps2_kbd_clk_out), + .ps2_dat_out(ps2_kbd_data_out), + + .ps2_clk_in(ps2_kbd_clk_in || !PS2WE), + .ps2_dat_in(ps2_kbd_data_in || !PS2WE), + + .rdata(kbd_data_host), + .rd(kbd_rd) +); + +reg [7:0] mouse_data; +reg mouse_we; +wire [8:0] mouse_data_host; +reg mouse_rd; + +ps2_device mouse +( + .clk_sys(clk_sys), + + .wdata(mouse_data), + .we(mouse_we), + + .ps2_clk(clk_ps2), + .ps2_clk_out(ps2_mouse_clk_out), + .ps2_dat_out(ps2_mouse_data_out), + + .ps2_clk_in(ps2_mouse_clk_in || !PS2WE), + .ps2_dat_in(ps2_mouse_data_in || !PS2WE), + + .rdata(mouse_data_host), + .rd(mouse_rd) +); + + +/////////////////////////////// DOWNLOADING /////////////////////////////// + +localparam UIO_FILE_TX = 8'h53; +localparam UIO_FILE_TX_DAT = 8'h54; +localparam UIO_FILE_INDEX = 8'h55; + +always@(posedge clk_sys) begin + reg [15:0] cmd; + reg has_cmd; + reg [24:0] addr; + reg wr; + reg [7:0] tmp; + + ioctl_wr <= wr; + wr <= 0; + + if(~io_enable) has_cmd <= 0; + else begin + if(io_strobe) begin + + if(!has_cmd) begin + cmd <= io_din; + has_cmd <= 1; + end else begin + + case(cmd) + UIO_FILE_INDEX: + begin + ioctl_index <= io_din[7:0]; + end + + UIO_FILE_TX: + begin + if(io_din[7:0]) begin + addr <= 0; + ioctl_download <= 1; + end else begin + ioctl_addr <= addr[24:1]; + ioctl_download <= 0; + end + end + + UIO_FILE_TX_DAT: + begin + if(addr[0]) begin + ioctl_addr <= addr[24:1]; + ioctl_dout <= {tmp, io_din[7:0]}; + wr <= 1; + end + tmp <= io_din[7:0]; + addr <= addr + 1'd1; + end + endcase + end + end + end +end + +endmodule + +////////////////////////////////////////////////////////////////////////////////// + + +module ps2_device #(parameter PS2_FIFO_BITS=5) +( + input clk_sys, + + input [7:0] wdata, + input we, + + input ps2_clk, + output reg ps2_clk_out, + output reg ps2_dat_out, + + input ps2_clk_in, + input ps2_dat_in, + + output [8:0] rdata, + input rd +); + + +(* ramstyle = "logic" *) reg [7:0] fifo[1<= 1)&&(tx_state < 9)) begin + ps2_dat_out <= tx_byte[0]; // data bits + tx_byte[6:0] <= tx_byte[7:1]; // shift down + if(tx_byte[0]) + parity <= !parity; + end + + // transmission of parity + if(tx_state == 9) ps2_dat_out <= parity; + + // transmission of stop bit + if(tx_state == 10) ps2_dat_out <= 1; // stop bit is 1 + + // advance state machine + if(tx_state < 11) tx_state <= tx_state + 1'd1; + else tx_state <= 0; + end + end + end + + if(~old_clk & ps2_clk) ps2_clk_out <= 1; + if(old_clk & ~ps2_clk) ps2_clk_out <= ((tx_state == 0) && (rx_state<2)); + +end + +endmodule diff --git a/sys/hq2x.sv b/sys/hq2x.sv new file mode 100644 index 0000000..02b8543 --- /dev/null +++ b/sys/hq2x.sv @@ -0,0 +1,416 @@ +// +// +// Copyright (c) 2012-2013 Ludvig Strigeus +// Copyright (c) 2017 Sorgelig +// +// This program is GPL Licensed. See COPYING for the full license. +// +// +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on + +`define BITS_TO_FIT(N) ( \ + N <= 2 ? 0 : \ + N <= 4 ? 1 : \ + N <= 8 ? 2 : \ + N <= 16 ? 3 : \ + N <= 32 ? 4 : \ + N <= 64 ? 5 : \ + N <= 128 ? 6 : \ + N <= 256 ? 7 : \ + N <= 512 ? 8 : \ + N <= 1024 ? 9 : \ + N <= 2048 ?10 : 11 ) + +module Hq2x #(parameter LENGTH, parameter HALF_DEPTH) +( + input clk, + input ce_x4, + input [DWIDTH:0] inputpixel, + input mono, + input disable_hq2x, + input reset_frame, + input reset_line, + input [1:0] read_y, + input [AWIDTH+1:0] read_x, + output [DWIDTH:0] outpixel +); + + +localparam AWIDTH = `BITS_TO_FIT(LENGTH); +localparam DWIDTH = HALF_DEPTH ? 11 : 23; + +wire [5:0] hqTable[256] = '{ + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 47, 35, 23, 15, 55, 39, + 19, 19, 26, 58, 19, 19, 26, 58, 23, 15, 35, 35, 23, 15, 7, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 55, 39, 23, 15, 51, 43, + 19, 19, 26, 58, 19, 19, 26, 58, 23, 15, 51, 35, 23, 15, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 61, 35, 35, 23, 61, 51, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 61, 7, 35, 23, 61, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 58, 23, 15, 51, 35, 23, 61, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 47, 35, 23, 15, 55, 39, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 55, 39, 23, 15, 51, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 39, 23, 15, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 39, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 7, 35, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 7, 43, + 19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 7, 35, 23, 15, 7, 43 +}; + +reg [23:0] Prev0, Prev1, Prev2, Curr0, Curr1, Next0, Next1, Next2; +reg [23:0] A, B, D, F, G, H; +reg [7:0] pattern, nextpatt; +reg [1:0] i; +reg [7:0] y; + +wire curbuf = y[0]; +reg prevbuf = 0; +wire iobuf = !curbuf; + +wire diff0, diff1; +DiffCheck diffcheck0(Curr1, (i == 0) ? Prev0 : (i == 1) ? Curr0 : (i == 2) ? Prev2 : Next1, diff0); +DiffCheck diffcheck1(Curr1, (i == 0) ? Prev1 : (i == 1) ? Next0 : (i == 2) ? Curr2 : Next2, diff1); + +wire [7:0] new_pattern = {diff1, diff0, pattern[7:2]}; + +wire [23:0] X = (i == 0) ? A : (i == 1) ? Prev1 : (i == 2) ? Next1 : G; +wire [23:0] blend_result; +Blend blender(hqTable[nextpatt], disable_hq2x, Curr0, X, B, D, F, H, blend_result); + +reg Curr2_addr1; +reg [AWIDTH:0] Curr2_addr2; +wire [23:0] Curr2 = HALF_DEPTH ? h2rgb(Curr2tmp) : Curr2tmp; +wire [DWIDTH:0] Curr2tmp; + +reg [AWIDTH:0] wrin_addr2; +reg [DWIDTH:0] wrpix; +reg wrin_en; + +function [23:0] h2rgb; + input [11:0] v; +begin + h2rgb = mono ? {v[7:0], v[7:0], v[7:0]} : {v[11:8],v[11:8],v[7:4],v[7:4],v[3:0],v[3:0]}; +end +endfunction + +function [11:0] rgb2h; + input [23:0] v; +begin + rgb2h = mono ? {4'b0000, v[23:20], v[19:16]} : {v[23:20], v[15:12], v[7:4]}; +end +endfunction + +hq2x_in #(.LENGTH(LENGTH), .DWIDTH(DWIDTH)) hq2x_in +( + .clk(clk), + + .rdaddr(Curr2_addr2), + .rdbuf(Curr2_addr1), + .q(Curr2tmp), + + .wraddr(wrin_addr2), + .wrbuf(iobuf), + .data(wrpix), + .wren(wrin_en) +); + +reg [1:0] wrout_addr1; +reg [AWIDTH+1:0] wrout_addr2; +reg wrout_en; +reg [DWIDTH:0] wrdata; + +hq2x_out #(.LENGTH(LENGTH), .DWIDTH(DWIDTH)) hq2x_out +( + .clk(clk), + + .rdaddr(read_x), + .rdbuf(read_y), + .q(outpixel), + + .wraddr(wrout_addr2), + .wrbuf(wrout_addr1), + .data(wrdata), + .wren(wrout_en) +); + +always @(posedge clk) begin + reg [AWIDTH:0] offs; + reg old_reset_line; + reg old_reset_frame; + + wrout_en <= 0; + wrin_en <= 0; + + if(ce_x4) begin + + pattern <= new_pattern; + + if(~&offs) begin + if (i == 0) begin + Curr2_addr1 <= prevbuf; + Curr2_addr2 <= offs; + end + if (i == 1) begin + Prev2 <= Curr2; + Curr2_addr1 <= curbuf; + Curr2_addr2 <= offs; + end + if (i == 2) begin + Next2 <= HALF_DEPTH ? h2rgb(inputpixel) : inputpixel; + wrpix <= inputpixel; + wrin_addr2 <= offs; + wrin_en <= 1; + end + if (i == 3) begin + offs <= offs + 1'd1; + end + + if(HALF_DEPTH) wrdata <= rgb2h(blend_result); + else wrdata <= blend_result; + + wrout_addr1 <= {curbuf, i[1]}; + wrout_addr2 <= {offs, i[1]^i[0]}; + wrout_en <= 1; + end + + if(i==3) begin + nextpatt <= {new_pattern[7:6], new_pattern[3], new_pattern[5], new_pattern[2], new_pattern[4], new_pattern[1:0]}; + {A, G} <= {Prev0, Next0}; + {B, F, H, D} <= {Prev1, Curr2, Next1, Curr0}; + {Prev0, Prev1} <= {Prev1, Prev2}; + {Curr0, Curr1} <= {Curr1, Curr2}; + {Next0, Next1} <= {Next1, Next2}; + end else begin + nextpatt <= {nextpatt[5], nextpatt[3], nextpatt[0], nextpatt[6], nextpatt[1], nextpatt[7], nextpatt[4], nextpatt[2]}; + {B, F, H, D} <= {F, H, D, B}; + end + + i <= i + 1'b1; + if(old_reset_line && ~reset_line) begin + old_reset_frame <= reset_frame; + offs <= 0; + i <= 0; + y <= y + 1'd1; + prevbuf <= curbuf; + if(old_reset_frame & ~reset_frame) begin + y <= 0; + prevbuf <= 0; + end + end + + old_reset_line <= reset_line; + end +end + +endmodule + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +module hq2x_in #(parameter LENGTH, parameter DWIDTH) +( + input clk, + + input [AWIDTH:0] rdaddr, + input rdbuf, + output[DWIDTH:0] q, + + input [AWIDTH:0] wraddr, + input wrbuf, + input [DWIDTH:0] data, + input wren +); + + localparam AWIDTH = `BITS_TO_FIT(LENGTH); + wire [DWIDTH:0] out[2]; + assign q = out[rdbuf]; + + hq2x_buf #(.NUMWORDS(LENGTH), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf0(clk,data,rdaddr,wraddr,wren && (wrbuf == 0),out[0]); + hq2x_buf #(.NUMWORDS(LENGTH), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf1(clk,data,rdaddr,wraddr,wren && (wrbuf == 1),out[1]); +endmodule + + +module hq2x_out #(parameter LENGTH, parameter DWIDTH) +( + input clk, + + input [AWIDTH:0] rdaddr, + input [1:0] rdbuf, + output[DWIDTH:0] q, + + input [AWIDTH:0] wraddr, + input [1:0] wrbuf, + input [DWIDTH:0] data, + input wren +); + + localparam AWIDTH = `BITS_TO_FIT(LENGTH*2); + wire [DWIDTH:0] out[4]; + assign q = out[rdbuf]; + + hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf0(clk,data,rdaddr,wraddr,wren && (wrbuf == 0),out[0]); + hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf1(clk,data,rdaddr,wraddr,wren && (wrbuf == 1),out[1]); + hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf2(clk,data,rdaddr,wraddr,wren && (wrbuf == 2),out[2]); + hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf3(clk,data,rdaddr,wraddr,wren && (wrbuf == 3),out[3]); +endmodule + + +module hq2x_buf #(parameter NUMWORDS, parameter AWIDTH, parameter DWIDTH) +( + input clock, + input [DWIDTH:0] data, + input [AWIDTH:0] rdaddress, + input [AWIDTH:0] wraddress, + input wren, + output logic [DWIDTH:0] q +); + +logic [DWIDTH:0] ram[0:NUMWORDS-1]; + +always_ff@(posedge clock) begin + if(wren) ram[wraddress] <= data; + q <= ram[rdaddress]; +end + +endmodule + +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +module DiffCheck +( + input [23:0] rgb1, + input [23:0] rgb2, + output result +); + + wire [7:0] r = rgb1[7:1] - rgb2[7:1]; + wire [7:0] g = rgb1[15:9] - rgb2[15:9]; + wire [7:0] b = rgb1[23:17] - rgb2[23:17]; + wire [8:0] t = $signed(r) + $signed(b); + wire [8:0] gx = {g[7], g}; + wire [9:0] y = $signed(t) + $signed(gx); + wire [8:0] u = $signed(r) - $signed(b); + wire [9:0] v = $signed({g, 1'b0}) - $signed(t); + + // if y is inside (-96..96) + wire y_inside = (y < 10'h60 || y >= 10'h3a0); + + // if u is inside (-16, 16) + wire u_inside = (u < 9'h10 || u >= 9'h1f0); + + // if v is inside (-24, 24) + wire v_inside = (v < 10'h18 || v >= 10'h3e8); + assign result = !(y_inside && u_inside && v_inside); +endmodule + +module InnerBlend +( + input [8:0] Op, + input [7:0] A, + input [7:0] B, + input [7:0] C, + output [7:0] O +); + + function [10:0] mul8x3; + input [7:0] op1; + input [2:0] op2; + begin + mul8x3 = 11'd0; + if(op2[0]) mul8x3 = mul8x3 + op1; + if(op2[1]) mul8x3 = mul8x3 + {op1, 1'b0}; + if(op2[2]) mul8x3 = mul8x3 + {op1, 2'b00}; + end + endfunction + + wire OpOnes = Op[4]; + wire [10:0] Amul = mul8x3(A, Op[7:5]); + wire [10:0] Bmul = mul8x3(B, {Op[3:2], 1'b0}); + wire [10:0] Cmul = mul8x3(C, {Op[1:0], 1'b0}); + wire [10:0] At = Amul; + wire [10:0] Bt = (OpOnes == 0) ? Bmul : {3'b0, B}; + wire [10:0] Ct = (OpOnes == 0) ? Cmul : {3'b0, C}; + wire [11:0] Res = {At, 1'b0} + Bt + Ct; + assign O = Op[8] ? A : Res[11:4]; +endmodule + +module Blend +( + input [5:0] rule, + input disable_hq2x, + input [23:0] E, + input [23:0] A, + input [23:0] B, + input [23:0] D, + input [23:0] F, + input [23:0] H, + output [23:0] Result +); + + reg [1:0] input_ctrl; + reg [8:0] op; + localparam BLEND0 = 9'b1_xxx_x_xx_xx; // 0: A + localparam BLEND1 = 9'b0_110_0_10_00; // 1: (A * 12 + B * 4) >> 4 + localparam BLEND2 = 9'b0_100_0_10_10; // 2: (A * 8 + B * 4 + C * 4) >> 4 + localparam BLEND3 = 9'b0_101_0_10_01; // 3: (A * 10 + B * 4 + C * 2) >> 4 + localparam BLEND4 = 9'b0_110_0_01_01; // 4: (A * 12 + B * 2 + C * 2) >> 4 + localparam BLEND5 = 9'b0_010_0_11_11; // 5: (A * 4 + (B + C) * 6) >> 4 + localparam BLEND6 = 9'b0_111_1_xx_xx; // 6: (A * 14 + B + C) >> 4 + localparam AB = 2'b00; + localparam AD = 2'b01; + localparam DB = 2'b10; + localparam BD = 2'b11; + wire is_diff; + DiffCheck diff_checker(rule[1] ? B : H, rule[0] ? D : F, is_diff); + + always @* begin + case({!is_diff, rule[5:2]}) + 1,17: {op, input_ctrl} = {BLEND1, AB}; + 2,18: {op, input_ctrl} = {BLEND1, DB}; + 3,19: {op, input_ctrl} = {BLEND1, BD}; + 4,20: {op, input_ctrl} = {BLEND2, DB}; + 5,21: {op, input_ctrl} = {BLEND2, AB}; + 6,22: {op, input_ctrl} = {BLEND2, AD}; + + 8: {op, input_ctrl} = {BLEND0, 2'bxx}; + 9: {op, input_ctrl} = {BLEND0, 2'bxx}; + 10: {op, input_ctrl} = {BLEND0, 2'bxx}; + 11: {op, input_ctrl} = {BLEND1, AB}; + 12: {op, input_ctrl} = {BLEND1, AB}; + 13: {op, input_ctrl} = {BLEND1, AB}; + 14: {op, input_ctrl} = {BLEND1, DB}; + 15: {op, input_ctrl} = {BLEND1, BD}; + + 24: {op, input_ctrl} = {BLEND2, DB}; + 25: {op, input_ctrl} = {BLEND5, DB}; + 26: {op, input_ctrl} = {BLEND6, DB}; + 27: {op, input_ctrl} = {BLEND2, DB}; + 28: {op, input_ctrl} = {BLEND4, DB}; + 29: {op, input_ctrl} = {BLEND5, DB}; + 30: {op, input_ctrl} = {BLEND3, BD}; + 31: {op, input_ctrl} = {BLEND3, DB}; + default: {op, input_ctrl} = {11{1'bx}}; + endcase + + // Setting op[8] effectively disables HQ2X because blend will always return E. + if (disable_hq2x) op[8] = 1; + end + + // Generate inputs to the inner blender. Valid combinations. + // 00: E A B + // 01: E A D + // 10: E D B + // 11: E B D + wire [23:0] Input1 = E; + wire [23:0] Input2 = !input_ctrl[1] ? A : + !input_ctrl[0] ? D : B; + + wire [23:0] Input3 = !input_ctrl[0] ? B : D; + InnerBlend inner_blend1(op, Input1[7:0], Input2[7:0], Input3[7:0], Result[7:0]); + InnerBlend inner_blend2(op, Input1[15:8], Input2[15:8], Input3[15:8], Result[15:8]); + InnerBlend inner_blend3(op, Input1[23:16], Input2[23:16], Input3[23:16], Result[23:16]); +endmodule diff --git a/sys/i2c.v b/sys/i2c.v new file mode 100644 index 0000000..911330f --- /dev/null +++ b/sys/i2c.v @@ -0,0 +1,69 @@ + +module I2C_Controller +( + input CLK, + + input START, + input [23:0] I2C_DATA, + output reg END = 1, + output reg ACK = 0, + + //I2C bus + output I2C_SCL, + inout I2C_SDA +); + + +// Clock Setting +parameter CLK_Freq = 50_000_000; // 50 MHz +parameter I2C_Freq = 400_000; // 400 KHz + +reg I2C_CLOCK; +always@(negedge CLK) begin + integer mI2C_CLK_DIV = 0; + if(mI2C_CLK_DIV < (CLK_Freq/I2C_Freq)) begin + mI2C_CLK_DIV <= mI2C_CLK_DIV + 1; + end else begin + mI2C_CLK_DIV <= 0; + I2C_CLOCK <= ~I2C_CLOCK; + end +end + +assign I2C_SCL = SCLK | I2C_CLOCK; +assign I2C_SDA = SDO ? 1'bz : 1'b0; + +reg SCLK = 1, SDO = 1; + +always @(posedge CLK) begin + reg old_clk; + reg old_st; + + reg [5:0] SD_COUNTER = 'b111111; + reg [0:31] SD; + + old_clk <= I2C_CLOCK; + old_st <= START; + + if(~old_st && START) begin + SCLK <= 1; + SDO <= 1; + ACK <= 0; + END <= 0; + SD <= {2'b10, I2C_DATA[23:16], 1'b1, I2C_DATA[15:8], 1'b1, I2C_DATA[7:0], 4'b1011}; + SD_COUNTER <= 0; + end else begin + if(~old_clk && I2C_CLOCK && ~&SD_COUNTER) begin + SD_COUNTER <= SD_COUNTER + 6'd1; + case(SD_COUNTER) + 01: SCLK <= 0; + 10,19,28: ACK <= ACK | I2C_SDA; + 29: SCLK <= 1; + 32: END <= 1; + endcase + end + + if(old_clk && ~I2C_CLOCK && ~SD_COUNTER[5]) SDO <= SD[SD_COUNTER[4:0]]; + end +end + +endmodule diff --git a/sys/i2s.v b/sys/i2s.v new file mode 100644 index 0000000..4de12b5 --- /dev/null +++ b/sys/i2s.v @@ -0,0 +1,85 @@ + +module i2s +#( + parameter CLK_RATE = 50000000, + parameter AUDIO_DW = 16, + parameter AUDIO_RATE = 96000 +) +( + input reset, + input clk_sys, + input half_rate, + + output reg sclk, + output reg lrclk, + output reg sdata, + + input [AUDIO_DW-1:0] left_chan, + input [AUDIO_DW-1:0] right_chan +); + +localparam WHOLE_CYCLES = (CLK_RATE) / (AUDIO_RATE*AUDIO_DW*4); +localparam ERROR_BASE = 10000; +localparam [63:0] ERRORS_PER_BIT = ((CLK_RATE * ERROR_BASE) / (AUDIO_RATE*AUDIO_DW*4)) - (WHOLE_CYCLES * ERROR_BASE); + +always @(posedge clk_sys) begin + reg [31:0] count_q; + reg [31:0] error_q; + reg [7:0] bit_cnt; + + reg [AUDIO_DW-1:0] left; + reg [AUDIO_DW-1:0] right; + + reg msclk; + reg ce; + + if (reset) begin + count_q <= 0; + error_q <= 0; + ce <= 0; + bit_cnt <= 1; + lrclk <= 1; + sclk <= 1; + msclk <= 1; + end + else + begin + if(count_q == WHOLE_CYCLES-1) begin + if (error_q < (ERROR_BASE - ERRORS_PER_BIT)) begin + error_q <= error_q + ERRORS_PER_BIT[31:0]; + count_q <= 0; + end else begin + error_q <= error_q + ERRORS_PER_BIT[31:0] - ERROR_BASE; + count_q <= count_q + 1; + end + end else if(count_q == WHOLE_CYCLES) begin + count_q <= 0; + end else begin + count_q <= count_q + 1; + end + + sclk <= msclk; + if(!count_q) begin + ce <= ~ce; + if(~half_rate || ce) begin + msclk <= ~msclk; + if(msclk) begin + if(bit_cnt >= AUDIO_DW) begin + bit_cnt <= 1; + lrclk <= ~lrclk; + if(lrclk) begin + left <= left_chan; + right <= right_chan; + end + end + else begin + bit_cnt <= bit_cnt + 1'd1; + end + sdata <= lrclk ? right[AUDIO_DW - bit_cnt] : left[AUDIO_DW - bit_cnt]; + end + end + end + end +end + +endmodule diff --git a/sys/ip/avalon_combiner.v b/sys/ip/avalon_combiner.v new file mode 100644 index 0000000..164906c --- /dev/null +++ b/sys/ip/avalon_combiner.v @@ -0,0 +1,60 @@ +// avalon_combiner.v + +`timescale 1 ps / 1 ps +module avalon_combiner +( + input wire clk, // clock.clk + input wire rst, // reset.reset + + output wire [6:0] mixer_address, // ctl_mixer.address + output wire [3:0] mixer_byteenable, // .byteenable + output wire mixer_write, // .write + output wire [31:0] mixer_writedata, // .writedata + input wire mixer_waitrequest, // .waitrequest + + output wire [6:0] scaler_address, // ctl_scaler.address + output wire [3:0] scaler_byteenable, // .byteenable + input wire scaler_waitrequest, // .waitrequest + output wire scaler_write, // .write + output wire [31:0] scaler_writedata, // .writedata + + output wire [7:0] video_address, // ctl_video.address + output wire [3:0] video_byteenable, // .byteenable + input wire video_waitrequest, // .waitrequest + output wire video_write, // .write + output wire [31:0] video_writedata, // .writedata + + output wire clock, // control.clock + output wire reset, // .reset + input wire [8:0] address, // .address + input wire write, // .write + input wire [31:0] writedata, // .writedata + output wire waitrequest // .waitrequest +); + +assign clock = clk; +assign reset = rst; + +assign mixer_address = address[6:0]; +assign scaler_address = address[6:0]; +assign video_address = address[7:0]; + +assign mixer_byteenable = 4'b1111; +assign scaler_byteenable = 4'b1111; +assign video_byteenable = 4'b1111; + +wire en_scaler = (address[8:7] == 0); +wire en_mixer = (address[8:7] == 1); +wire en_video = address[8]; + +assign mixer_write = en_mixer & write; +assign scaler_write = en_scaler & write; +assign video_write = en_video & write; + +assign mixer_writedata = writedata; +assign scaler_writedata = writedata; +assign video_writedata = writedata; + +assign waitrequest = (en_mixer & mixer_waitrequest) | (en_scaler & scaler_waitrequest) | (en_video & video_waitrequest); + +endmodule diff --git a/sys/ip/avalon_combiner_hw.tcl b/sys/ip/avalon_combiner_hw.tcl new file mode 100644 index 0000000..10e491f --- /dev/null +++ b/sys/ip/avalon_combiner_hw.tcl @@ -0,0 +1,204 @@ +# TCL File Generated by Component Editor 16.1 +# Sat Mar 25 22:55:53 CST 2017 +# DO NOT MODIFY + + +# +# avalon_combiner "avalon_combiner" v1.0 +# 2017.03.25.22:55:53 +# +# + +# +# request TCL package from ACDS 16.1 +# +package require -exact qsys 16.1 + + +# +# module avalon_combiner +# +set_module_property DESCRIPTION "" +set_module_property NAME avalon_combiner +set_module_property VERSION 1.0 +set_module_property INTERNAL false +set_module_property OPAQUE_ADDRESS_MAP true +set_module_property AUTHOR sorgelig +set_module_property DISPLAY_NAME avalon_combiner +set_module_property INSTANTIATE_IN_SYSTEM_MODULE true +set_module_property EDITABLE true +set_module_property REPORT_TO_TALKBACK false +set_module_property ALLOW_GREYBOX_GENERATION false +set_module_property REPORT_HIERARCHY false + + +# +# file sets +# +add_fileset QUARTUS_SYNTH QUARTUS_SYNTH "" "" +set_fileset_property QUARTUS_SYNTH TOP_LEVEL avalon_combiner +set_fileset_property QUARTUS_SYNTH ENABLE_RELATIVE_INCLUDE_PATHS false +set_fileset_property QUARTUS_SYNTH ENABLE_FILE_OVERWRITE_MODE true +add_fileset_file avalon_combiner.v VERILOG PATH avalon_combiner.v TOP_LEVEL_FILE + + +# +# parameters +# + + +# +# display items +# + + +# +# connection point clock +# +add_interface clock clock end +set_interface_property clock clockRate 0 +set_interface_property clock ENABLED true +set_interface_property clock EXPORT_OF "" +set_interface_property clock PORT_NAME_MAP "" +set_interface_property clock CMSIS_SVD_VARIABLES "" +set_interface_property clock SVD_ADDRESS_GROUP "" + +add_interface_port clock clk clk Input 1 + + +# +# connection point reset +# +add_interface reset reset end +set_interface_property reset associatedClock clock +set_interface_property reset synchronousEdges DEASSERT +set_interface_property reset ENABLED true +set_interface_property reset EXPORT_OF "" +set_interface_property reset PORT_NAME_MAP "" +set_interface_property reset CMSIS_SVD_VARIABLES "" +set_interface_property reset SVD_ADDRESS_GROUP "" + +add_interface_port reset rst reset Input 1 + + +# +# connection point ctl_mixer +# +add_interface ctl_mixer avalon start +set_interface_property ctl_mixer addressUnits WORDS +set_interface_property ctl_mixer associatedClock clock +set_interface_property ctl_mixer associatedReset reset +set_interface_property ctl_mixer bitsPerSymbol 8 +set_interface_property ctl_mixer burstOnBurstBoundariesOnly false +set_interface_property ctl_mixer burstcountUnits WORDS +set_interface_property ctl_mixer doStreamReads false +set_interface_property ctl_mixer doStreamWrites false +set_interface_property ctl_mixer holdTime 0 +set_interface_property ctl_mixer linewrapBursts false +set_interface_property ctl_mixer maximumPendingReadTransactions 0 +set_interface_property ctl_mixer maximumPendingWriteTransactions 0 +set_interface_property ctl_mixer readLatency 0 +set_interface_property ctl_mixer readWaitTime 1 +set_interface_property ctl_mixer setupTime 0 +set_interface_property ctl_mixer timingUnits Cycles +set_interface_property ctl_mixer writeWaitTime 0 +set_interface_property ctl_mixer ENABLED true +set_interface_property ctl_mixer EXPORT_OF "" +set_interface_property ctl_mixer PORT_NAME_MAP "" +set_interface_property ctl_mixer CMSIS_SVD_VARIABLES "" +set_interface_property ctl_mixer SVD_ADDRESS_GROUP "" + +add_interface_port ctl_mixer mixer_address address Output 7 +add_interface_port ctl_mixer mixer_byteenable byteenable Output 4 +add_interface_port ctl_mixer mixer_write write Output 1 +add_interface_port ctl_mixer mixer_writedata writedata Output 32 +add_interface_port ctl_mixer mixer_waitrequest waitrequest Input 1 + + +# +# connection point ctl_scaler +# +add_interface ctl_scaler avalon start +set_interface_property ctl_scaler addressUnits WORDS +set_interface_property ctl_scaler associatedClock clock +set_interface_property ctl_scaler associatedReset reset +set_interface_property ctl_scaler bitsPerSymbol 8 +set_interface_property ctl_scaler burstOnBurstBoundariesOnly false +set_interface_property ctl_scaler burstcountUnits WORDS +set_interface_property ctl_scaler doStreamReads false +set_interface_property ctl_scaler doStreamWrites false +set_interface_property ctl_scaler holdTime 0 +set_interface_property ctl_scaler linewrapBursts false +set_interface_property ctl_scaler maximumPendingReadTransactions 0 +set_interface_property ctl_scaler maximumPendingWriteTransactions 0 +set_interface_property ctl_scaler readLatency 0 +set_interface_property ctl_scaler readWaitTime 1 +set_interface_property ctl_scaler setupTime 0 +set_interface_property ctl_scaler timingUnits Cycles +set_interface_property ctl_scaler writeWaitTime 0 +set_interface_property ctl_scaler ENABLED true +set_interface_property ctl_scaler EXPORT_OF "" +set_interface_property ctl_scaler PORT_NAME_MAP "" +set_interface_property ctl_scaler CMSIS_SVD_VARIABLES "" +set_interface_property ctl_scaler SVD_ADDRESS_GROUP "" + +add_interface_port ctl_scaler scaler_address address Output 7 +add_interface_port ctl_scaler scaler_byteenable byteenable Output 4 +add_interface_port ctl_scaler scaler_waitrequest waitrequest Input 1 +add_interface_port ctl_scaler scaler_write write Output 1 +add_interface_port ctl_scaler scaler_writedata writedata Output 32 + + +# +# connection point ctl_video +# +add_interface ctl_video avalon start +set_interface_property ctl_video addressUnits WORDS +set_interface_property ctl_video associatedClock clock +set_interface_property ctl_video associatedReset reset +set_interface_property ctl_video bitsPerSymbol 8 +set_interface_property ctl_video burstOnBurstBoundariesOnly false +set_interface_property ctl_video burstcountUnits WORDS +set_interface_property ctl_video doStreamReads false +set_interface_property ctl_video doStreamWrites false +set_interface_property ctl_video holdTime 0 +set_interface_property ctl_video linewrapBursts false +set_interface_property ctl_video maximumPendingReadTransactions 0 +set_interface_property ctl_video maximumPendingWriteTransactions 0 +set_interface_property ctl_video readLatency 0 +set_interface_property ctl_video readWaitTime 1 +set_interface_property ctl_video setupTime 0 +set_interface_property ctl_video timingUnits Cycles +set_interface_property ctl_video writeWaitTime 0 +set_interface_property ctl_video ENABLED true +set_interface_property ctl_video EXPORT_OF "" +set_interface_property ctl_video PORT_NAME_MAP "" +set_interface_property ctl_video CMSIS_SVD_VARIABLES "" +set_interface_property ctl_video SVD_ADDRESS_GROUP "" + +add_interface_port ctl_video video_address address Output 8 +add_interface_port ctl_video video_byteenable byteenable Output 4 +add_interface_port ctl_video video_waitrequest waitrequest Input 1 +add_interface_port ctl_video video_write write Output 1 +add_interface_port ctl_video video_writedata writedata Output 32 + + +# +# connection point control +# +add_interface control conduit end +set_interface_property control associatedClock clock +set_interface_property control associatedReset reset +set_interface_property control ENABLED true +set_interface_property control EXPORT_OF "" +set_interface_property control PORT_NAME_MAP "" +set_interface_property control CMSIS_SVD_VARIABLES "" +set_interface_property control SVD_ADDRESS_GROUP "" + +add_interface_port control address address Input 9 +add_interface_port control write write Input 1 +add_interface_port control writedata writedata Input 32 +add_interface_port control waitrequest waitrequest Output 1 +add_interface_port control clock clock Output 1 +add_interface_port control reset reset Output 1 + diff --git a/sys/ip/de10_hps_hw.tcl b/sys/ip/de10_hps_hw.tcl new file mode 100644 index 0000000..491400a --- /dev/null +++ b/sys/ip/de10_hps_hw.tcl @@ -0,0 +1,3706 @@ +# (C) 2001-2017 Intel Corporation. All rights reserved. +# Your use of Intel Corporation's design tools, logic functions and other +# software and tools, and its AMPP partner logic functions, and any output +# files any of the foregoing (including device programming or simulation +# files), and any associated documentation or information are expressly subject +# to the terms and conditions of the Intel Program License Subscription +# Agreement, Intel MegaCore Function License Agreement, or other applicable +# license agreement, including, without limitation, that your use is for the +# sole purpose of programming logic devices manufactured by Intel and sold by +# Intel or its authorized distributors. Please refer to the applicable +# agreement for further details. + + +# This IP is modified standard Altera HPS IP. +# Direct DDR3 SDRAM access has been removed since it won't work together with HPS DDR3 SDRAM access. +# FPGA access the memory through MPFE (FPGA2SDRAM bridge). +# By removing direct DDR3 SDRAM access synthesis time has been reduced by 3 times! + + +package require -exact qsys 12.0 +package require -exact altera_terp 1.0 +package require quartus::advanced_wysiwyg + +set_module_property NAME altera_hps_lite +set_module_property VERSION 16.1 +set_module_property AUTHOR "Altera Corporation/Sorgelig" +set_module_property SUPPORTED_DEVICE_FAMILIES {CYCLONEV ARRIAV} + +set_module_property DISPLAY_NAME "DE10-nano Hard Processor System" +set_module_property INSTANTIATE_IN_SYSTEM_MODULE true +set_module_property EDITABLE false +set_module_property HIDE_FROM_SOPC true +set_module_property HIDE_FROM_QUARTUS true + +add_documentation_link "HPS User Guide for Cyclone V" "http://www.altera.com/literature/hb/cyclone-v/cv_5v4.pdf" +add_documentation_link "HPS User Guide for Arria V" "http://www.altera.com/literature/hb/arria-v/av_5v4.pdf" + +set alt_mem_if_tcl_libs_dir "$env(QUARTUS_ROOTDIR)/../ip/altera/alt_mem_if/alt_mem_if_tcl_packages" +if {[lsearch -exact $auto_path $alt_mem_if_tcl_libs_dir] == -1} { + lappend auto_path $alt_mem_if_tcl_libs_dir +} + +package require alt_mem_if::gui::system_info + +source $env(QUARTUS_ROOTDIR)/../ip/altera/hps/util/constants.tcl +source $env(QUARTUS_ROOTDIR)/../ip/altera/hps/util/procedures.tcl +source $env(QUARTUS_ROOTDIR)/../ip/altera/hps/util/pin_mux.tcl +source $env(QUARTUS_ROOTDIR)/../ip/altera/hps/util/pin_mux_db.tcl +source $env(QUARTUS_ROOTDIR)/../ip/altera/hps/util/locations.tcl +source $env(QUARTUS_ROOTDIR)/../ip/altera/hps/util/ui.tcl +source $env(QUARTUS_ROOTDIR)/../ip/altera/hps/altera_hps/clocks.tcl +source $env(QUARTUS_ROOTDIR)/../ip/altera/hps/altera_hps/clock_manager.tcl + +proc add_storage_parameter {name { default_value {} } } { + add_parameter $name string $default_value "" + set_parameter_property $name derived true + set_parameter_property $name visible false +} + +proc add_reset_parameters {} { + set group_name "Resets" + add_display_item "FPGA Interfaces" $group_name "group" "" + + add_parameter S2FCLK_COLDRST_Enable boolean false "" + set_parameter_property S2FCLK_COLDRST_Enable display_name "Enable HPS-to-FPGA cold reset output" + set_parameter_property S2FCLK_COLDRST_Enable group $group_name + + add_parameter S2FCLK_PENDINGRST_Enable boolean false "" + set_parameter_property S2FCLK_PENDINGRST_Enable display_name "Enable HPS warm reset handshake signals" + set_parameter_property S2FCLK_PENDINGRST_Enable group $group_name + + add_parameter F2SCLK_DBGRST_Enable boolean false "" + set_parameter_property F2SCLK_DBGRST_Enable display_name "Enable FPGA-to-HPS debug reset request" + set_parameter_property F2SCLK_DBGRST_Enable group $group_name + + add_parameter F2SCLK_WARMRST_Enable boolean false "" + set_parameter_property F2SCLK_WARMRST_Enable display_name "Enable FPGA-to-HPS warm reset request" + set_parameter_property F2SCLK_WARMRST_Enable group $group_name + + add_parameter F2SCLK_COLDRST_Enable boolean false "" + set_parameter_property F2SCLK_COLDRST_Enable display_name "Enable FPGA-to-HPS cold reset request" + set_parameter_property F2SCLK_COLDRST_Enable group $group_name + +} + +proc list_h2f_interrupt_groups {} { + return { + "CAN" "CLOCKPERIPHERAL" "CTI" + "DMA" "EMAC" "FPGAMANAGER" + "GPIO" "I2CEMAC" "I2CPERIPHERAL" + "L4TIMER" "NAND" "OSCTIMER" + "QSPI" "SDMMC" "SPIMASTER" + "SPISLAVE" "UART" "USB" + "WATCHDOG" + } +} + +proc get_h2f_interrupt_descriptions {data_ref} { + upvar 1 $data_ref data + array set data { + "DMA" "Enable DMA interrupts" + "EMAC" "Enable EMAC interrupts (for EMAC0 and EMAC1)" + "USB" "Enable USB interrupts" + "CAN" "Enable CAN interrupts" + "SDMMC" "Enable SD/MMC interrupt" + "NAND" "Enable NAND interrupt" + "QSPI" "Enable Quad SPI interrupt" + "SPIMASTER" "Enable SPI master interrupts" + "SPISLAVE" "Enable SPI slave interrupts" + "I2CPERIPHERAL" "Enable I2C peripheral interrupts (for I2C0 and I2C1)" + "I2CEMAC" "Enable I2C-EMAC interrupts (for I2C2 and I2C3)" + "UART" "Enable UART interrupts" + "GPIO" "Enable GPIO interrupts" + "L4TIMER" "Enable L4 timer interrupts" + "OSCTIMER" "Enable OSC timer interrupts" + "WATCHDOG" "Enable watchdog interrupts" + "CLOCKPERIPHERAL" "Enable clock peripheral interrupts" + "FPGAMANAGER" "Enable FPGA manager interrupt" + "CTI" "Enable CTI interrupts" + } +} + +proc load_h2f_interrupt_table {functions_by_group_ref + width_by_function_ref + inverted_by_function_ref} { + upvar 1 $functions_by_group_ref functions_by_group + upvar 1 $width_by_function_ref width_by_function + upvar 1 $inverted_by_function_ref inverted_by_function + array set functions_by_group { + "DMA" {"dma" "dma_abort" } + "EMAC" {"emac0" "emac1" } + "USB" {"usb0" "usb1" } + "CAN" {"can0" "can1" } + "SDMMC" {"sdmmc" } + "NAND" {"nand" } + "QSPI" {"qspi" } + "SPIMASTER" {"spi0" "spi1" } + "SPISLAVE" {"spi2" "spi3" } + "I2CPERIPHERAL" {"i2c0" "i2c1" } + "I2CEMAC" {"i2c_emac0" "i2c_emac1" } + "UART" {"uart0" "uart1" } + "GPIO" {"gpio0" "gpio1" "gpio2"} + "L4TIMER" {"l4sp0" "l4sp1" } + "OSCTIMER" {"osc0" "osc1" } + "WATCHDOG" {"wdog0" "wdog1" } + "CLOCKPERIPHERAL" {"clkmgr" "mpuwakeup" } + "FPGAMANAGER" {"fpga_man" } + "CTI" {"cti" } + } + array set width_by_function { + "dma" 8 + "cti" 2 + } + array set inverted_by_function { + "cti" 1 + } +} + +proc add_interrupt_parameters {} { + set top_group_name "Interrupts" + add_display_item "FPGA Interfaces" $top_group_name "group" "" + + # add_display_item $group_name "f2h_interrupts_label" "text" "FPGA-to-HPS" + add_parameter F2SINTERRUPT_Enable boolean false + set_parameter_property F2SINTERRUPT_Enable enabled true + set_parameter_property F2SINTERRUPT_Enable display_name "Enable FPGA-to-HPS Interrupts" + set_parameter_property F2SINTERRUPT_Enable group $top_group_name + + set inner_group_name "HPS-to-FPGA" + add_display_item $top_group_name $inner_group_name "group" "" + get_h2f_interrupt_descriptions descriptions_by_group + set interrupt_groups [list_h2f_interrupt_groups] + foreach interrupt_group $interrupt_groups { + set parameter "S2FINTERRUPT_${interrupt_group}_Enable" + add_parameter $parameter boolean false + set_parameter_property $parameter enabled true + set_parameter_property $parameter display_name $descriptions_by_group($interrupt_group) + set_parameter_property $parameter group $inner_group_name + } +} + +proc add_dma_parameters {} { + set group_name "DMA Peripheral Request" + add_display_item "FPGA Interfaces" $group_name "group" "" + add_display_item $group_name "DMA Table" "group" "table" + + add_parameter DMA_PeriphId_DERIVED string_list {0 1 2 3 4 5 6 7} + set_parameter_property DMA_PeriphId_DERIVED display_name "Peripheral Request ID" + set_parameter_property DMA_PeriphId_DERIVED derived true + set_parameter_property DMA_PeriphId_DERIVED display_hint "FIXED_SIZE" + set_parameter_property DMA_PeriphId_DERIVED group "DMA Table" + + add_parameter DMA_Enable string_list {"No" "No" "No" "No" "No" "No" "No" "No"} + set_parameter_property DMA_Enable allowed_ranges {"Yes" "No"} + set_parameter_property DMA_Enable display_name "Enabled" + set_parameter_property DMA_Enable display_hint "FIXED_SIZE" + set_parameter_property DMA_Enable group "DMA Table" +} + +proc range_from_zero {end} { + set result [list] + for {set i 0} {$i <= $end} {incr i} { + lappend result $i + } + return $result +} + +proc create_generic_parameters {} { + + ::alt_mem_if::util::hwtcl_utils::_add_parameter SYS_INFO_DEVICE_FAMILY STRING "" + set_parameter_property SYS_INFO_DEVICE_FAMILY SYSTEM_INFO DEVICE_FAMILY + set_parameter_property SYS_INFO_DEVICE_FAMILY VISIBLE FALSE + + ::alt_mem_if::util::hwtcl_utils::_add_parameter DEVICE_FAMILY STRING "" + set_parameter_property DEVICE_FAMILY DERIVED true + set_parameter_property DEVICE_FAMILY VISIBLE FALSE + + return 1 +} + +create_generic_parameters + +add_display_item "" "FPGA Interfaces" "group" "tab" +add_display_item "" "Peripheral Pins" "group" "tab" +add_display_item "" "HPS Clocks" "group" "tab" +add_clock_tab "HPS Clocks" + +add_display_item "FPGA Interfaces" "General" "group" "" + +add_parameter MPU_EVENTS_Enable boolean true +set_parameter_property MPU_EVENTS_Enable display_name "Enable MPU standby and event signals" +set_parameter_property MPU_EVENTS_Enable description "Enables elaboration of the mpu_events interface." +set_parameter_property MPU_EVENTS_Enable group "General" + +add_parameter GP_Enable boolean false +set_parameter_property GP_Enable display_name "Enable general purpose signals" +set_parameter_property GP_Enable description "Enables elaboration of interface h2f_gp." +set_parameter_property GP_Enable group "General" + +add_parameter DEBUGAPB_Enable boolean false +set_parameter_property DEBUGAPB_Enable display_name "Enable Debug APB interface" +set_parameter_property DEBUGAPB_Enable description "Enables elaboration of Debug APB interfaces." +set_parameter_property DEBUGAPB_Enable group "General" + +add_parameter STM_Enable boolean false +set_parameter_property STM_Enable display_name "Enable System Trace Macrocell hardware events" +set_parameter_property STM_Enable description "Enables elaboration of interface stm_hwevents." +set_parameter_property STM_Enable group "General" + +add_parameter CTI_Enable boolean false +set_parameter_property CTI_Enable display_name "Enable FPGA Cross Trigger Interface" +set_parameter_property CTI_Enable description "Enables elaboration of interface cti_trigger, cti_clk_in." +set_parameter_property CTI_Enable group "General" + +add_parameter TPIUFPGA_Enable boolean false +set_parameter_property TPIUFPGA_Enable display_name "Enable FPGA Trace Port Interface Unit" +set_parameter_property TPIUFPGA_Enable description "Enables elaboration of TPIU FPGA interfaces." +set_parameter_property TPIUFPGA_Enable group "General" + +add_parameter TPIUFPGA_alt boolean false +set_parameter_property TPIUFPGA_alt display_name "Enable FPGA Trace Port Alternate FPGA Interface" +set_parameter_property TPIUFPGA_alt description "When the trace port is enabled, it creates an interface compatible with the Arria 10 Trace Interface. (This just moves the clock_in port into the same conduit)" +set_parameter_property TPIUFPGA_alt group "General" +set_parameter_property TPIUFPGA_alt enabled false + + +add_parameter BOOTFROMFPGA_Enable boolean false +set_parameter_property BOOTFROMFPGA_Enable enabled true +set_parameter_property BOOTFROMFPGA_Enable display_name "Enable boot from fpga signals" +set_parameter_property BOOTFROMFPGA_Enable description "Enables elaboration of interface boot_from_fpga." +set_parameter_property BOOTFROMFPGA_Enable group "General" + +add_parameter TEST_Enable boolean false +set_parameter_property TEST_Enable enabled true +set_parameter_property TEST_Enable display_name "Enable Test Interface" +set_parameter_property TEST_Enable group "General" + +add_parameter HLGPI_Enable boolean false +set_parameter_property HLGPI_Enable enabled true +set_parameter_property HLGPI_Enable display_name "Enable HLGPI Interface" +set_parameter_property HLGPI_Enable group "General" + +add_display_item "FPGA Interfaces" "Boot and Clock Selection" "group" "" +add_parameter BSEL_EN boolean false +set_parameter_property BSEL_EN enabled true +set_parameter_property BSEL_EN display_name "Enable boot selection from FPGA" +set_parameter_property BSEL_EN group "Boot and Clock Selection" +set_parameter_property BSEL_EN visible false +set_parameter_property BSEL_EN enabled false + +add_parameter BSEL integer 1 +set_parameter_property BSEL allowed_ranges {"1:FPGA" "2:NAND Flash (1.8v)" "3:NAND Flash (3.0v)" "4:SD/MMC External Transceiver (1.8v)" "5:SD/MMC Internal Transceiver (3.0v)" "6:Quad SPI Flash (1.8v)" "7:Quad SPI Flash (3.0v)"} +set_parameter_property BSEL display_name "Boot selection from FPGA" +set_parameter_property BSEL group "Boot and Clock Selection" +set_parameter_property BSEL visible false +set_parameter_property BSEL enabled false + +add_parameter CSEL_EN boolean false +set_parameter_property CSEL_EN enabled true +set_parameter_property CSEL_EN display_name "Enable clock selection from FPGA" +set_parameter_property CSEL_EN group "Boot and Clock Selection" +set_parameter_property CSEL_EN visible false +set_parameter_property CSEL_EN enabled false + +add_parameter CSEL integer 0 +set_parameter_property CSEL allowed_ranges {"0:CSEL_0" "1:CSEL_1" "2:CSEL_2" "3:CSEL_3"} +set_parameter_property CSEL display_name "Clock selection from FPGA" +set_parameter_property CSEL group "Boot and Clock Selection" +set_parameter_property CSEL visible false +set_parameter_property CSEL enabled false + +add_display_item "FPGA Interfaces" "AXI Bridges" "group" "" +add_parameter F2S_Width integer 2 +set_parameter_property F2S_Width allowed_ranges {"0:Unused" "1:32-bit" "2:64-bit" "3:128-bit"} +set_parameter_property F2S_Width display_name "FPGA-to-HPS interface width" +set_parameter_property F2S_Width hdl_parameter true +set_parameter_property F2S_Width group "AXI Bridges" + +add_parameter S2F_Width integer 2 +set_parameter_property S2F_Width allowed_ranges {"0:Unused" "1:32-bit" "2:64-bit" "3:128-bit"} +set_parameter_property S2F_Width display_name "HPS-to-FPGA interface width" +set_parameter_property S2F_Width hdl_parameter true +set_parameter_property S2F_Width group "AXI Bridges" + +add_parameter LWH2F_Enable string true +set_parameter_property LWH2F_Enable display_name "Lightweight HPS-to-FPGA interface width" +set_parameter_property LWH2F_Enable description "The lightweight HPS-to-FPGA bridge provides a secondary, fixed-width, smaller address space, lower-performance master interface to the FPGA fabric. Use the lightweight HPS-to-FPGA bridge for high-latency, low-bandwidth traffic, such as memory-mapped register accesses of FPGA peripherals. This approach diverts traffic from the high-performance HPS-to-FPGA bridge, which can improve overall performance." +set_parameter_property LWH2F_Enable allowed_ranges {"true:32-bit" "false:Unused"} +set_parameter_property LWH2F_Enable group "AXI Bridges" + + +set group_name "FPGA-to-HPS SDRAM Interface" +add_display_item "FPGA Interfaces" $group_name "group" "" +add_display_item $group_name "f2sdram_label" "text" "Click the '+' and '-' buttons to add and remove FPGA-to-HPS SDRAM ports." +set table_name "F2SDRAM Settings" +add_display_item $group_name $table_name "group" "table" + +add_parameter F2SDRAM_Name_DERIVED string_list {"f2h_sdram0"} +set_parameter_property F2SDRAM_Name_DERIVED derived true +set_parameter_property F2SDRAM_Name_DERIVED display_name "Name" +set_parameter_property F2SDRAM_Name_DERIVED group $table_name + +add_parameter F2SDRAM_Type string_list [list [F2HSDRAM_AXI3]] +set_parameter_property F2SDRAM_Type allowed_ranges [list [F2HSDRAM_AXI3] [F2HSDRAM_AVM] [F2HSDRAM_AVM_WRITEONLY] [F2HSDRAM_AVM_READONLY]] +set_parameter_property F2SDRAM_Type display_name "Type" +set_parameter_property F2SDRAM_Type group $table_name + +add_parameter F2SDRAM_Width integer_list {"64"} +set_parameter_property F2SDRAM_Width allowed_ranges "32,64,128,256" +set_parameter_property F2SDRAM_Width display_name "Width" +set_parameter_property F2SDRAM_Width group $table_name +set_parameter_update_callback F2SDRAM_Width on_altered_f2sdram_width +# TODO: f2sdram derived parameters for resource counts in the table +# TODO: f2sdram derived parameters for remaining resources, not a part of the table + +add_storage_parameter F2SDRAM_Width_Last_Size 1 +add_storage_parameter F2SDRAM_CMD_PORT_USED 0 +add_storage_parameter F2SDRAM_WR_PORT_USED 0 +add_storage_parameter F2SDRAM_RD_PORT_USED 0 +add_storage_parameter F2SDRAM_RST_PORT_USED 0 +set_parameter_property F2SDRAM_Width_Last_Size group $group_name +set_parameter_property F2SDRAM_CMD_PORT_USED group $group_name +set_parameter_property F2SDRAM_WR_PORT_USED group $group_name +set_parameter_property F2SDRAM_RD_PORT_USED group $group_name +set_parameter_property F2SDRAM_RST_PORT_USED group $group_name + +#Parameter to export Bonding_out signal from fpga2sdram Atom +add_parameter BONDING_OUT_ENABLED boolean false +set_parameter_property BONDING_OUT_ENABLED display_name "Enable BONDING-OUT signals" +set_parameter_property BONDING_OUT_ENABLED group $group_name +set_parameter_property BONDING_OUT_ENABLED enabled false +set_parameter_property BONDING_OUT_ENABLED visible false + + +proc on_altered_f2sdram_width { param } { + set old_size [get_parameter_value F2SDRAM_Width_Last_Size] + set current_value [get_parameter_value F2SDRAM_Width] + set current_size [llength $current_value] + + if {$current_size == $old_size + 1} { ;# look for case of newly added row + set last_element_index [expr {$current_size - 1}] + set new_value [lreplace $current_value $last_element_index $last_element_index "64"] + set_parameter_value F2SDRAM_Width $new_value + } +} + +add_reset_parameters + +add_dma_parameters + +add_interrupt_parameters + + set group_name "EMAC ptp interface" + add_display_item "FPGA Interfaces" $group_name "group" "" + + add_parameter EMAC0_PTP boolean false + set_parameter_property EMAC0_PTP display_name "Enable EMAC0 Precision Time Protocol (PTP) FPGA Interface" + set_parameter_property EMAC0_PTP hdl_parameter false + set_parameter_property EMAC0_PTP enabled false + set_parameter_property EMAC0_PTP group $group_name + set_parameter_property EMAC0_PTP description "When the EMAC is connected to the HPS IO via the Pinmux, the IEEE 1588 Precision Time Protocol (PTP) interface can be accessed through the FPGA. When the EMAC connects to the FPGA, the PTP signals are always available." + + add_parameter EMAC1_PTP boolean false + set_parameter_property EMAC1_PTP display_name "Enable EMAC1 Precision Time Protocol (PTP) FPGA Interface" + set_parameter_property EMAC1_PTP hdl_parameter false + set_parameter_property EMAC1_PTP enabled false + set_parameter_property EMAC1_PTP group $group_name + set_parameter_property EMAC1_PTP description "When the EMAC is connected to the HPS IO via the Pinmux, the IEEE 1588 Precision Time Protocol (PTP) interface can be accessed through the FPGA. When the EMAC connects to the FPGA, the PTP signals are always available." + + +proc make_mode_display_name {peripheral} { + set default_suffix "mode" + array set custom_suffix_by_peripheral { + USB0 "PHY interface mode" + USB1 "PHY interface mode" + } + if {[info exists custom_suffix_by_peripheral($peripheral)]} { + set suffix $custom_suffix_by_peripheral($peripheral) + } else { + set suffix $default_suffix + } + + set display_name "${peripheral} ${suffix}" + return $display_name +} + +proc add_peripheral_pin_muxing_parameters {} { + set TOP_LEVEL_GROUP_NAME "Peripheral Pins" + + + foreach group_name [list_group_names] { + add_display_item $TOP_LEVEL_GROUP_NAME $group_name "group" "" + + foreach peripheral_name [peripherals_in_group $group_name] { + set pin_muxing_param_name "${peripheral_name}_PinMuxing" + set mode_param_name "${peripheral_name}_Mode" + add_parameter $pin_muxing_param_name string [UNUSED_MUX_VALUE] + set_parameter_property $pin_muxing_param_name enabled false + set_parameter_property $pin_muxing_param_name display_name "${peripheral_name} pin" + set_parameter_property $pin_muxing_param_name allowed_ranges [UNUSED_MUX_VALUE] + set_parameter_property $pin_muxing_param_name group $group_name + set_parameter_update_callback $pin_muxing_param_name on_altered_peripheral_pin_muxing $peripheral_name + + set mode_display_name [make_mode_display_name $peripheral_name] + add_parameter $mode_param_name string [NA_MODE_VALUE] + set_parameter_property $mode_param_name enabled false + set_parameter_property $mode_param_name display_name $mode_display_name + set_parameter_property $mode_param_name allowed_ranges [NA_MODE_VALUE] + set_parameter_property $mode_param_name group $group_name + + if {[string match "*EMAC*" $peripheral_name]} { + set_parameter_update_callback $mode_param_name on_emac_mode_switch_internal $peripheral_name + } + } + } +} +add_peripheral_pin_muxing_parameters + +proc add_gpio_parameters {} { + set TOP_LEVEL_GROUP_NAME "Peripheral Pins" + set group_name "Peripherals Mux Table" + set table_name "Conflict Table" + + add_display_item $TOP_LEVEL_GROUP_NAME $group_name "group" "" + #add_display_item $group_name $table_name "group" "table" + + add_parameter Customer_Pin_Name_DERIVED string_list {} + set_parameter_property Customer_Pin_Name_DERIVED display_name "Pin Name" + set_parameter_property Customer_Pin_Name_DERIVED derived true + set_parameter_property Customer_Pin_Name_DERIVED display_hint "FIXED_SIZE" + set_parameter_property Customer_Pin_Name_DERIVED visible false + # set_parameter_property Customer_Pin_Name_DERIVED group $table_name + + add_parameter GPIO_Conflict_DERIVED string_list {} + set_parameter_property GPIO_Conflict_DERIVED display_name "Used by" + set_parameter_property GPIO_Conflict_DERIVED derived true + set_parameter_property GPIO_Conflict_DERIVED display_hint "FIXED_SIZE" + set_parameter_property GPIO_Conflict_DERIVED visible false + #set_parameter_property GPIO_Conflict_DERIVED group $table_name + + add_parameter GPIO_Name_DERIVED string_list {} + set_parameter_property GPIO_Name_DERIVED display_name "GPIO" + set_parameter_property GPIO_Name_DERIVED derived true + set_parameter_property GPIO_Name_DERIVED display_hint "FIXED_SIZE" + set_parameter_property GPIO_Name_DERIVED visible false + #set_parameter_property GPIO_Name_DERIVED group $table_name + + # TODO: change? + set max_possible_gpio_options 100 + set enable_list [list] + for {set i 0} {$i < $max_possible_gpio_options} {incr i} { + lappend enable_list "No" + } + + add_parameter GPIO_Enable string_list $enable_list + set_parameter_property GPIO_Enable allowed_ranges {"Yes" "No"} + set_parameter_property GPIO_Enable display_name "GPIO Enabled" + set_parameter_property GPIO_Enable visible false + # set_parameter_property GPIO_Enable group $table_name + + add_parameter LOANIO_Name_DERIVED string_list {} + set_parameter_property LOANIO_Name_DERIVED display_name "Loan I/O" + set_parameter_property LOANIO_Name_DERIVED derived true + set_parameter_property LOANIO_Name_DERIVED display_hint "FIXED_SIZE" + set_parameter_property LOANIO_Name_DERIVED visible false + + add_parameter GPIO_Pin_Used_DERIVED boolean false + set_parameter_property GPIO_Pin_Used_DERIVED display_name "GPIO Pin Used" + set_parameter_property GPIO_Pin_Used_DERIVED derived true + set_parameter_property GPIO_Pin_Used_DERIVED display_hint "GPIO Pin Used" + set_parameter_property GPIO_Pin_Used_DERIVED visible false + + add_parameter LOANIO_Enable string_list $enable_list + set_parameter_property LOANIO_Enable allowed_ranges {"Yes" "No"} + set_parameter_property LOANIO_Enable display_name "Loan I/O Enabled" + set_parameter_property LOANIO_Enable visible false + #set_parameter_property LOANIO_Enable group $table_name + + + +} +add_gpio_parameters + +proc add_reset_parameters {} { + set group_name "Resets" + add_display_item "FPGA Interfaces" $group_name "group" "" + + add_parameter S2FCLK_COLDRST_Enable boolean false "" + set_parameter_property S2FCLK_COLDRST_Enable display_name "Enable HPS-to-FPGA cold reset output" + set_parameter_property S2FCLK_COLDRST_Enable group $group_name + + add_parameter S2FCLK_PENDINGRST_Enable boolean false "" + set_parameter_property S2FCLK_PENDINGRST_Enable display_name "Enable HPS warm reset handshake signals" + set_parameter_property S2FCLK_PENDINGRST_Enable group $group_name + + add_parameter F2SCLK_DBGRST_Enable boolean false "" + set_parameter_property F2SCLK_DBGRST_Enable display_name "Enable FPGA-to-HPS debug reset request" + set_parameter_property F2SCLK_DBGRST_Enable group $group_name + + add_parameter F2SCLK_WARMRST_Enable boolean false "" + set_parameter_property F2SCLK_WARMRST_Enable display_name "Enable FPGA-to-HPS warm reset request" + set_parameter_property F2SCLK_WARMRST_Enable group $group_name + + add_parameter F2SCLK_COLDRST_Enable boolean false "" + set_parameter_property F2SCLK_COLDRST_Enable display_name "Enable FPGA-to-HPS cold reset request" + set_parameter_property F2SCLK_COLDRST_Enable group $group_name + +} + +proc add_java_gui_parameters {} { + set TOP_LEVEL_GROUP_NAME "Peripheral Pins" + set group_name "Peripherals Mux Table" + + add_display_item $TOP_LEVEL_GROUP_NAME $group_name "group" "" + # add_display_item $group_name the_widget "group" "" + + add_parameter JAVA_CONFLICT_PIN string_list {} + set_parameter_property JAVA_CONFLICT_PIN derived true + set_parameter_property JAVA_CONFLICT_PIN visible false + + + add_parameter JAVA_GUI_PIN_LIST string_list {} + set_parameter_property JAVA_GUI_PIN_LIST derived true + set_parameter_property JAVA_GUI_PIN_LIST visible false + + set peripherals [list_peripheral_names] + set widget_parameter [list \ + Customer_Pin_Name_DERIVED Customer_Pin_Name_DERIVED \ + GPIO_Name_DERIVED GPIO_Name_DERIVED \ + LOANIO_Name_DERIVED LOANIO_Name_DERIVED \ + LOANIO_Enable LOANIO_Enable \ + GPIO_Enable GPIO_Enable \ + JAVA_CONFLICT_PIN GUI_Conflict_Pins_List \ + JAVA_GUI_PIN_LIST GUI_GPIO_Pins_List] + + foreach peripheral_name $peripherals { + add_parameter "JAVA_${peripheral_name}_DATA" string "" + set_parameter_property "JAVA_${peripheral_name}_DATA" derived true + set_parameter_property "JAVA_${peripheral_name}_DATA" visible false + + lappend widget_parameter "JAVA_${peripheral_name}_DATA" + lappend widget_parameter "${peripheral_name}_pin_muxing" + lappend widget_parameter "${peripheral_name}_PinMuxing" + lappend widget_parameter "${peripheral_name}_PinMuxing" + lappend widget_parameter "${peripheral_name}_Mode" + lappend widget_parameter "${peripheral_name}_Mode" + } + + add_display_item $group_name the_widget "group" + set_display_item_property the_widget widget [list ../widget/pin_mux_widget.jar Altera_hps_widget] + set_display_item_property the_widget widget_parameter_map $widget_parameter +} + +add_java_gui_parameters + +############################################## +# Clocks! +# +# All clock enable parameters go here. +# Clock frequency parameters also go here. All +# the parameters need to be declared regardless +# of whether the clock will be exercised. +# +# Validation logic will enable/show frequency +# parameters based on whether the actual clock +# is being elaborated. +# +# There are four categories of clocks in this +# component: inputs on SoC I/O +# outputs on SoC I/O +# inputs on FPGA pins +# outputs on FPGA pins +# +# Inputs on SoC I/O have user-input parameters +# so the data can be consumed by downstream +# embedded software tools. +# Outputs on SoC I/O need not have frequency +# information recorded. +# Inputs on FPGA pins have system info parameters +# so the data can be consumed by downstream +# embedded software tools. +# Outputs on FPGA pins have user input parameters +# to be consumed by Quartus via SDC. +# +############################################## +proc add_clock_parameters {} { + set TOP_LEVEL_GROUP_NAME "Input Clocks" + + set group_name "User Clocks" + add_display_item $TOP_LEVEL_GROUP_NAME $group_name "group" "" + + # fake group + set group_name "FPGA Interface Clocks" + add_display_item $TOP_LEVEL_GROUP_NAME $group_name "group" "" + + foreach interface { + f2h_axi_clock h2f_axi_clock h2f_lw_axi_clock + f2h_sdram0_clock f2h_sdram1_clock f2h_sdram2_clock + f2h_sdram3_clock f2h_sdram4_clock f2h_sdram5_clock + h2f_cti_clock h2f_tpiu_clock_in h2f_debug_apb_clock + } { + set parameter "[string toupper ${interface}]_FREQ" + add_parameter $parameter integer 100 "" + set_parameter_property $parameter display_name "${interface} clock frequency" + set_parameter_property $parameter system_info_type "CLOCK_RATE" + set_parameter_property $parameter system_info_arg $interface + set_parameter_property $parameter visible false + set_parameter_property $parameter group $group_name + } + + set peripherals [list_peripheral_names] + + # TODO: Remove the following for 12.0 + set group_name "Peripheral FPGA Clocks" + add_display_item $TOP_LEVEL_GROUP_NAME $group_name "group" "" + + # Add parameter explicitly for cross-emac ptp since it doesn't belong to a single peripheral + set parameter [form_peripheral_fpga_input_clock_frequency_parameter emac_ptp_ref_clock] + add_parameter $parameter integer 100 "" + set_parameter_property $parameter display_name "EMAC emac_ptp_ref_clock clock frequency" + set_parameter_property $parameter group $group_name + set_parameter_property $parameter system_info_type "CLOCK_RATE" + set_parameter_property $parameter system_info_arg emac_ptp_ref_clock + set_parameter_property $parameter visible false + + foreach peripheral $peripherals { + set clocks [get_peripheral_fpga_input_clocks $peripheral] + foreach clock $clocks { + set parameter [form_peripheral_fpga_input_clock_frequency_parameter $clock] + add_parameter $parameter integer 100 "" + set_parameter_property $parameter display_name "${peripheral} ${clock} clock frequency" + set_parameter_property $parameter group $group_name + set_parameter_property $parameter system_info_type "CLOCK_RATE" + set_parameter_property $parameter system_info_arg $clock + set_parameter_property $parameter visible false + } + + set clocks [get_peripheral_fpga_output_clocks $peripheral] + foreach clock $clocks { + set parameter [form_peripheral_fpga_output_clock_frequency_parameter $clock] + if { [string match "*emac?_md*" $clock]} { + add_parameter $parameter float 2.5 "" + } elseif { [string match "*emac?_gtx_clk*" $clock] } { + add_parameter $parameter integer 125 "" + } else { + add_parameter $parameter integer 100 "" + if { [string compare $peripheral "SDIO" ] == 0 } { + set_parameter_property $parameter visible false + } + } + set_parameter_property $parameter display_name "${peripheral} ${clock} clock frequency" + set_parameter_property $parameter group $group_name + set_parameter_property $parameter units Megahertz + set_parameter_property $parameter allowedRanges {1:1000} + } + + } +} +add_clock_parameters + +add_parameter hps_device_family string "" "" +set_parameter_property hps_device_family derived true +set_parameter_property hps_device_family visible false + +add_parameter device_name string "" "" +set_parameter_property device_name system_info {DEVICE} +set_parameter_property device_name visible false + +add_parameter quartus_ini_hps_ip_enable_all_peripheral_fpga_interfaces boolean "" "" +set_parameter_property quartus_ini_hps_ip_enable_all_peripheral_fpga_interfaces system_info_type quartus_ini +set_parameter_property quartus_ini_hps_ip_enable_all_peripheral_fpga_interfaces system_info_arg hps_ip_enable_all_peripheral_fpga_interfaces +set_parameter_property quartus_ini_hps_ip_enable_all_peripheral_fpga_interfaces visible false + +add_parameter quartus_ini_hps_ip_enable_emac0_peripheral_fpga_interface boolean "" "" +set_parameter_property quartus_ini_hps_ip_enable_emac0_peripheral_fpga_interface system_info_type quartus_ini +set_parameter_property quartus_ini_hps_ip_enable_emac0_peripheral_fpga_interface system_info_arg hps_ip_enable_emac0_peripheral_fpga_interface +set_parameter_property quartus_ini_hps_ip_enable_emac0_peripheral_fpga_interface visible false + +add_parameter quartus_ini_hps_ip_enable_test_interface boolean "" "" +set_parameter_property quartus_ini_hps_ip_enable_test_interface system_info_type quartus_ini +set_parameter_property quartus_ini_hps_ip_enable_test_interface system_info_arg hps_ip_enable_test_interface +set_parameter_property quartus_ini_hps_ip_enable_test_interface visible false + +add_parameter quartus_ini_hps_ip_fast_f2sdram_sim_model boolean "" "" +set_parameter_property quartus_ini_hps_ip_fast_f2sdram_sim_model system_info_type quartus_ini +set_parameter_property quartus_ini_hps_ip_fast_f2sdram_sim_model system_info_arg hps_ip_fast_f2sdram_sim_model +set_parameter_property quartus_ini_hps_ip_fast_f2sdram_sim_model visible false + +add_parameter quartus_ini_hps_ip_suppress_sdram_synth boolean "" "" +set_parameter_property quartus_ini_hps_ip_suppress_sdram_synth system_info_type quartus_ini +set_parameter_property quartus_ini_hps_ip_suppress_sdram_synth system_info_arg hps_ip_suppress_sdram_synth +set_parameter_property quartus_ini_hps_ip_suppress_sdram_synth visible false + +add_parameter quartus_ini_hps_ip_enable_low_speed_serial_fpga_interfaces boolean "" "" +set_parameter_property quartus_ini_hps_ip_enable_low_speed_serial_fpga_interfaces system_info_type quartus_ini +set_parameter_property quartus_ini_hps_ip_enable_low_speed_serial_fpga_interfaces system_info_arg hps_ip_enable_low_speed_serial_fpga_interfaces +set_parameter_property quartus_ini_hps_ip_enable_low_speed_serial_fpga_interfaces visible false + +add_parameter quartus_ini_hps_ip_enable_bsel_csel boolean "" "" +set_parameter_property quartus_ini_hps_ip_enable_bsel_csel system_info_type quartus_ini +set_parameter_property quartus_ini_hps_ip_enable_bsel_csel system_info_arg hps_ip_enable_bsel_csel +set_parameter_property quartus_ini_hps_ip_enable_bsel_csel visible false + +add_parameter quartus_ini_hps_ip_f2sdram_bonding_out boolean "" "" +set_parameter_property quartus_ini_hps_ip_f2sdram_bonding_out system_info_type quartus_ini +set_parameter_property quartus_ini_hps_ip_f2sdram_bonding_out system_info_arg hps_ip_enable_f2sdram_bonding_out +set_parameter_property quartus_ini_hps_ip_f2sdram_bonding_out visible false + + +add_parameter quartus_ini_hps_emif_pll boolean "" "" +set_parameter_property quartus_ini_hps_emif_pll system_info_type quartus_ini +set_parameter_property quartus_ini_hps_emif_pll system_info_arg hps_emif_pll +set_parameter_property quartus_ini_hps_emif_pll visible false + + +proc load_test_iface_definition {} { + set csv_file $::env(QUARTUS_ROOTDIR)/../ip/altera/hps/altera_hps/test_iface.csv + + set data [list] + set count 0 + csv_foreach_row $csv_file cols { + incr count + if {$count == 1} { + continue + } + + lassign_trimmed $cols port width dir + lappend data $port $width $dir + } + return $data +} +add_storage_parameter test_iface_definition [load_test_iface_definition] + +# order of interfaces per peripheral should be kept +# order of ports per interface should be kept +proc load_periph_ifaces_db {} { + set interfaces_file $::env(QUARTUS_ROOTDIR)/../ip/altera/hps/altera_hps/fpga_peripheral_interfaces.csv + set peripherals_file $::env(QUARTUS_ROOTDIR)/../ip/altera/hps/altera_hps/fpga_peripheral_atoms.csv + set ports_file $::env(QUARTUS_ROOTDIR)/../ip/altera/hps/altera_hps/fpga_interface_ports.csv + set pins_file $::env(QUARTUS_ROOTDIR)/../ip/altera/hps/altera_hps/fpga_port_pins.csv + set bfm_types_file $::env(QUARTUS_ROOTDIR)/../ip/altera/hps/altera_hps/fpga_bfm_types.csv + + # peripherals and interfaces + set peripherals([ORDERED_NAMES]) [list] + funset interface_ports + set count 0 + set PERIPHERAL_INTERFACES_PROPERTIES_COLUMNS_START 4 + csv_foreach_row $interfaces_file cols { + incr count + # skip header + if {$count == 1} { + set ordered_names [list] + set length [llength $cols] + for {set col $PERIPHERAL_INTERFACES_PROPERTIES_COLUMNS_START} {$col < $length} {incr col} { + set col_value [lindex $cols $col] + if {$col_value != ""} { + set property_to_col($col_value) $col + lappend ordered_names $col_value + } + } + set property_to_col([ORDERED_NAMES]) $ordered_names + continue + } + + set peripheral_name [string trim [lindex $cols 0]] + set interface_name [string trim [lindex $cols 1]] + set type [string trim [lindex $cols 2]] + set dir [string trim [lindex $cols 3]] + + funset peripheral + if {[info exists peripherals($peripheral_name)]} { + array set peripheral $peripherals($peripheral_name) + } else { + funset interfaces + set interfaces([ORDERED_NAMES]) [list] + set peripheral(interfaces) [array get interfaces] + set ordered_names $peripherals([ORDERED_NAMES]) + lappend ordered_names $peripheral_name + set peripherals([ORDERED_NAMES]) $ordered_names + } + funset interfaces + array set interfaces $peripheral(interfaces) + set ordered_names $interfaces([ORDERED_NAMES]) + lappend ordered_names $interface_name + set interfaces([ORDERED_NAMES]) $ordered_names + funset interface + set interface(type) $type + set interface(direction) $dir + funset properties + foreach property $property_to_col([ORDERED_NAMES]) { + set col $property_to_col($property) + set property_value [lindex $cols $col] + + if {$property_value != ""} { + # Add Meta Property + if { [string compare [string index ${property} 0] "@" ] == 0 } { + set interface(${property}) ${property_value} + } else { + set properties($property) $property_value + } + } + } + + set interface(properties) [array get properties] + + set interfaces($interface_name) [array get interface] + set peripheral(interfaces) [array get interfaces] + set peripherals($peripheral_name) [array get peripheral] + + funset ports + set ports([ORDERED_NAMES]) [list] + set interface_ports($interface_name) [array get ports] + } + set count 0 + csv_foreach_row $peripherals_file cols { ;# peripheral atom and location table + incr count + + # skip header + if {$count == 1} { + continue + } + + set peripheral_name [string trim [lindex $cols 0]] + set atom_name [string trim [lindex $cols 1]] + + funset peripheral + if {[info exists peripherals($peripheral_name)]} { + array set peripheral $peripherals($peripheral_name) + } else { + # Assume that if a peripheral hasn't be recognized until now, we won't be using it + continue + } + set peripheral(atom_name) $atom_name + set peripherals($peripheral_name) [array get peripheral] + } + add_parameter DB_periph_ifaces string [array get peripherals] "" + set_parameter_property DB_periph_ifaces derived true + set_parameter_property DB_periph_ifaces visible false + + set p [array get peripherals] + send_message debug "DB_periph_ifaces: ${p}" + + # ports + array set ports_to_pins {} + # # prepopulate interface_ports with names of interfaces that are known + # foreach {peripheral_name peripheral_string} [array get peripherals] { + # array set peripheral_array $peripheral_string + # foreach interface_name [array names peripheral_array] { + # set interface_ports($interface_name) {} + # } + # } + set count 0 + csv_foreach_row $ports_file cols { + incr count + + # skip header + if {$count == 1} continue + + set interface_name [string trim [lindex $cols 0]] + set port_name [string trim [lindex $cols 1]] + set role [string trim [lindex $cols 2]] + set dir [string trim [lindex $cols 3]] + set atom_signal_name [string trim [lindex $cols 4]] + + funset interface + array set interface $interface_ports($interface_name) + set ordered_names $interface([ORDERED_NAMES]) + lappend ordered_names $port_name + set interface([ORDERED_NAMES]) $ordered_names + + funset port + set port(role) $role + set port(direction) $dir + set port(atom_signal_name) $atom_signal_name + set interface($port_name) [array get port] + set interface_ports($interface_name) [array get interface] + + set ports_to_pins($port_name) {} + } + add_parameter DB_iface_ports string [array get interface_ports] "" + set_parameter_property DB_iface_ports derived true + set_parameter_property DB_iface_ports visible false + + set p [array get interface_ports] + send_message debug "DB_iface_ports: ${p}" + + # peripheral signals to ports + set count 0 + csv_foreach_row $pins_file cols { + incr count + + # skip header + if {$count == 1} continue + + set peripheral_name [string trim [lindex $cols 0]] + set pin_name [string trim [lindex $cols 1]] + set port_name [string trim [lindex $cols 2]] + + set is_multibit_signal [regexp {^([a-zA-Z0-9_]+)\[([0-9]+)\]} $port_name match real_name bit] + if {$is_multibit_signal == 0} { + set bit 0 + } else { + set port_name $real_name + } + + if {[info exists ports_to_pins($port_name)] == 0} { + send_message error "Peripheral ${peripheral_name} signal ${pin_name} is defined but corresponding FPGA signal ${port_name}\[${bit}\] is not" + } else { + funset port + array set port $ports_to_pins($port_name) + + if {[info exists port($bit)]} { + # collision! + send_message error "Signal ${port_name}\[${bit}\] is having original assignment ${peripheral_name}.${port($bit)} replaced with ${peripheral_name}.${pin_name}" + } + set port($bit) $pin_name + set ports_to_pins($port_name) [array get port] + } + } + add_parameter DB_port_pins string [array get ports_to_pins] "" + set_parameter_property DB_port_pins derived true + set_parameter_property DB_port_pins visible false + + set p [array get ports_to_pins] + send_message debug "DB_port_pins: ${p}" + + # bfm types + set count 0 + funset bfm_types + csv_foreach_row $bfm_types_file cols { + incr count + + # skip header + if {$count == 1} continue + + set bfm_type_name [string trim [lindex $cols 0]] + set property_name [string trim [lindex $cols 1]] + set value [string trim [lindex $cols 2]] + + if {[info exists bfm_types($bfm_type_name)] == 0} { + set bfm_types($bfm_type_name) {} + } + funset bfm_type + array set bfm_type $bfm_types($bfm_type_name) + set bfm_type($property_name) $value + set bfm_types($bfm_type_name) [array get bfm_type] + } + add_parameter DB_bfm_types string [array get bfm_types] "" + set_parameter_property DB_bfm_types derived true + set_parameter_property DB_bfm_types visible false + # TODO: what to do so that mode information on a peripheral.pin basis can be used for elaboration??? +} + +# only run during class creation +load_periph_ifaces_db + +####################### +##### Composition ##### +####################### + +namespace eval ::fpga_interfaces { + source $env(QUARTUS_ROOTDIR)/../ip/altera/hps/altera_interface_generator/api.tcl +} + +namespace eval ::hps_io { + namespace eval internal { + source $env(QUARTUS_ROOTDIR)/../ip/altera/hps/altera_interface_generator/api.tcl + } + variable pins + + proc add_peripheral {peripheral_name atom_name location} { + internal::add_module_instance $peripheral_name $atom_name $location + } + + # oe used in tristate output and inout + # out used in output and inout + # in used in input and inout + proc add_pin {peripheral_name pin_name dir location in_port out_port oe_port} { + variable pins + lappend pins [list $peripheral_name $pin_name $dir $location $in_port $out_port $oe_port] + } + + proc process_pins {} { + variable pins + + set interface_name "hps_io" + set hps_io_interface_created 0 + funset ports_used ;# set of inst/ports used + funset port_wire ;# map of ports to aliased wires + foreach pin $pins { ;# Check for multiple uses of the same port and create wires for those cases + lassign $pin peripheral_name pin_name dir location in_port out_port oe_port + + # check to see if port is used multiple times + foreach port_part [list $in_port $out_port $oe_port] { + if {$port_part != "" && [info exists ports_used($port_part)]} { + # Assume only outputs will be used multiple times. Inputs would be an error + if {[info exists port_wire($port_part)] == 0} { + set port_wire($port_part) [internal::allocate_wire] + # Drive new wire with port + internal::set_wire_port_fragments $port_wire($port_part) driven_by $port_part + } + } + set ports_used($port_part) 1 + } + } + + set qip [list] + foreach pin $pins { + lassign $pin peripheral_name pin_name dir location in_port out_port oe_port + foreach port_part_ref {in_port out_port oe_port} { ;# Replace ports with wires if needed + set port_part [set $port_part_ref] + if {[info exists port_wire($port_part)]} { + set $port_part_ref [internal::wire_tofragment $port_wire($port_part)] + } + } + + # Hook things up + set instance_name [string tolower $peripheral_name] ;# is this necessary??? + if {$hps_io_interface_created == 0} { + set hps_io_interface_created 1 + internal::add_interface $interface_name conduit input + } + set export_signal_name "hps_io_${instance_name}_${pin_name}" + internal::add_interface_port $interface_name $export_signal_name $export_signal_name $dir 1 + if {[string compare $dir "input"] == 0} { + internal::set_port_fragments $interface_name $export_signal_name $in_port + internal::add_raw_sdc_constraint "set_false_path -from \[get_ports ${interface_name}_${export_signal_name}\] -to *" + } elseif {[string compare $dir "output"] == 0} { + if {[string compare $oe_port "" ] == 0} { + internal::set_port_fragments $interface_name $export_signal_name $out_port + internal::add_raw_sdc_constraint "set_false_path -from * -to \[get_ports ${interface_name}_${export_signal_name}\]" + } else { + internal::set_port_tristate_output $interface_name $export_signal_name $out_port $oe_port + internal::add_raw_sdc_constraint "set_false_path -from * -to \[get_ports ${interface_name}_${export_signal_name}\]" + } + } else { + internal::set_port_fragments $interface_name $export_signal_name $in_port + internal::set_port_tristate_output $interface_name $export_signal_name $out_port $oe_port + internal::add_raw_sdc_constraint "set_false_path -from \[get_ports ${interface_name}_${export_signal_name}\] -to *" + internal::add_raw_sdc_constraint "set_false_path -from * -to \[get_ports ${interface_name}_${export_signal_name}\]" + } + set path_to_pin "hps_io|border|${export_signal_name}\[0\]" + set location_assignment "set_instance_assignment -name HPS_LOCATION ${location} -entity %entityName% -to ${path_to_pin}" + lappend qip $location_assignment + } + set_qip_strings $qip + } + + proc init {} { + internal::init + variable pins [list] + } + + proc serialize {var_name} { + upvar 1 $var_name data + process_pins + internal::serialize data + } +} + +set_module_property composition_callback compose + +proc compose {} { + # synchronize device families between the EMIF and HPS parameter sets + set_parameter_value hps_device_family [get_parameter_value SYS_INFO_DEVICE_FAMILY] + fpga_interfaces::init + fpga_interfaces::set_bfm_types [array get DB_bfm_types] + + hps_io::init + validate + elab 0 + + update_hps_to_fpga_clock_frequency_parameters + + + fpga_interfaces::serialize fpga_interfaces_data + + add_instance fpga_interfaces altera_interface_generator + set_instance_parameter_value fpga_interfaces interfaceDefinition [array get fpga_interfaces_data] + + expose_border fpga_interfaces $fpga_interfaces_data(interfaces) + + declare_cmsis_svd $fpga_interfaces_data(interfaces) + + clear_array temp_array +} + +proc logicalview_dtg {} { + + set hard_peripheral_logical_view_dir $::env(QUARTUS_ROOTDIR)/../ip/altera/hps/hard_peripheral_logical_view + + source "$hard_peripheral_logical_view_dir/common/hps_utils.tcl" + + source "$hard_peripheral_logical_view_dir/hps_periphs/hps_periphs.tcl" + + set f2h_present [ expr [ get_parameter_value F2S_Width ] != 0] + set h2f_present [ expr [ get_parameter_value S2F_Width ] != 0] + set F2S_Width [ get_parameter_value F2S_Width ] + set S2F_Width [ get_parameter_value S2F_Width ] + set h2f_lw_present [ expr [ string compare [ get_parameter_value LWH2F_Enable ] "true" ] == 0 ] + set LWH2F_Enable [ get_parameter_value LWH2F_Enable ] + set device_family [get_parameter_value SYS_INFO_DEVICE_FAMILY] + + # Need to add whole bunch of device tree generation parameters here (dtg) + # Getting whether is it single or dual core by checking the device family. List of single core: + # Cyclone V SE + regsub "^.* V" $device_family "" se_family + regsub " " $se_family "" se_family + + set number_of_a9 0 + if { [string toupper $se_family] == "SE"} { + set number_of_a9 1 + } else { + set number_of_a9 2 + } + + set F2SDRAM_Width [get_parameter_value F2SDRAM_Width] + set F2SDRAM_Type [get_parameter_value F2SDRAM_Type] + set quartus_ini_hps_ip_f2sdram_bonding_out [get_parameter_value quartus_ini_hps_ip_f2sdram_bonding_out] + set BONDING_OUT_ENABLED [get_parameter_value BONDING_OUT_ENABLED] + add_instance clk_0 hps_clk_src + hps_utils_add_instance_clk_reset clk_0 bridges hps_bridge_avalon + set_instance_parameter_value bridges F2S_Width $F2S_Width + set_instance_parameter_value bridges S2F_Width $S2F_Width + set_instance_parameter_value bridges BONDING_OUT_ENABLED $BONDING_OUT_ENABLED + set_instance_parameter_value bridges LWH2F_Enable $LWH2F_Enable + set_instance_parameter_value bridges quartus_ini_hps_ip_f2sdram_bonding_out $quartus_ini_hps_ip_f2sdram_bonding_out + add_interface h2f_reset reset output + set_interface_property h2f_reset EXPORT_OF bridges.h2f_reset + set_interface_property h2f_reset PORT_NAME_MAP "h2f_rst_n h2f_rst_n" + + set rows [llength $F2SDRAM_Width] + set type_list $F2SDRAM_Type + set append_type_list "" + set append_type_width "" + set total_command_port 0 + set total_write_port 0 + set total_read_port 0 + if {$rows > 0} { + for {set i 0} {${i} < $rows} {incr i} { + set type_choice [lindex $type_list $i] + set type_width [lindex $F2SDRAM_Width $i] + if { [string compare $type_choice [F2HSDRAM_AVM]] == 0 } { + set type_id 1 + set total_command_port [expr $total_command_port + 1] + if {$type_width == 128} { + set total_write_port [expr $total_write_port + 2] + set total_read_port [expr $total_read_port + 2] + } elseif {$type_width == 256 } { + set total_write_port [expr $total_write_port + 4] + set total_read_port [expr $total_read_port + 4] + } else { + set total_write_port [expr $total_write_port + 1] + set total_read_port [expr $total_read_port + 1] + } + } elseif { [string compare $type_choice [F2HSDRAM_AVM_WRITEONLY]] == 0 } { + set type_id 2 + set total_command_port [expr $total_command_port + 1] + if {$type_width == 128} { + set total_write_port [expr $total_write_port + 2] + } elseif {$type_width == 256 } { + set total_write_port [expr $total_write_port + 4] + } else { + set total_write_port [expr $total_write_port + 1] + } + } elseif { [string compare $type_choice [F2HSDRAM_AVM_READONLY]] == 0 } { + set type_id 3 + set total_command_port [expr $total_command_port + 1] + if {$type_width == 128} { + set total_read_port [expr $total_read_port + 2] + } elseif {$type_width == 256 } { + set total_read_port [expr $total_read_port + 4] + } else { + set total_read_port [expr $total_read_port + 1] + } + } else { + set type_id 0 + if { [ expr $total_command_port % 2 ] } { + incr total_command_port 1 + } + set total_command_port [expr $total_command_port + 2] + if {$type_width == 128} { + set total_write_port [expr $total_write_port + 2] + set total_read_port [expr $total_read_port + 2] + } elseif {$type_width == 256 } { + set total_write_port [expr $total_write_port + 4] + set total_read_port [expr $total_read_port + 4] + } else { + set total_write_port [expr $total_write_port + 1] + set total_read_port [expr $total_read_port + 1] + } + } + + if {$total_command_port > 6} { + if {$type_id == 0} { + send_message error "No command ports available to allocate AXI Interface f2h_sdram${i}" + } else { + send_message error "No command ports available to allocate Avalon-MM Interface f2h_sdram${i}" + } + } + if {$total_read_port > 4} { + if {$type_id == 0} { + send_message error "No read ports available to allocate AXI Interface f2h_sdram${i}" + } else { + send_message error "No read ports available to allocate Avalon-MM Interface f2h_sdram${i}" + } + } + if {$total_write_port > 4} { + if {$type_id == 0} { + send_message error "No write ports available to allocate AXI Interface f2h_sdram${i}" + } else { + send_message error "No write ports available to allocate Avalon-MM Interface f2h_sdram${i}" + } + } + if {$total_command_port < 7 && $total_write_port < 5 && $total_read_port < 5} { + lappend append_type_list $type_id + lappend append_type_width $type_width + } + } + } + set_instance_parameter_value bridges F2SDRAM_Type $append_type_list + set_instance_parameter_value bridges F2SDRAM_Width $append_type_width + set total_command_port 0 + set total_write_port 0 + set total_read_port 0 + set bonding_out_signal [expr { [string compare [get_parameter_value BONDING_OUT_ENABLED] "true"] == 0} && {[string compare [get_parameter_value quartus_ini_hps_ip_f2sdram_bonding_out] "true"] == 0}] + + if {$rows > 0} { + for {set i 0} {${i} < $rows} {incr i} { + + set type_choice [lindex $type_list $i] + set type_width [lindex $F2SDRAM_Width $i] + + if { [string compare $type_choice [F2HSDRAM_AVM]] == 0 } { + set type "avalon" + set total_command_port [expr $total_command_port + 1] + if {$type_width == 128} { + set total_write_port [expr $total_write_port + 2] + set total_read_port [expr $total_read_port + 2] + } elseif {$type_width == 256 } { + set total_write_port [expr $total_write_port + 4] + set total_read_port [expr $total_read_port + 4] + } else { + set total_write_port [expr $total_write_port + 1] + set total_read_port [expr $total_read_port + 1] + } + set sdram_data "f2h_sdram${i}_ADDRESS f2h_sdram${i}_ADDRESS f2h_sdram${i}_BURSTCOUNT f2h_sdram${i}_BURSTCOUNT f2h_sdram${i}_WAITREQUEST f2h_sdram${i}_WAITREQUEST f2h_sdram${i}_READDATA f2h_sdram${i}_READDATA f2h_sdram${i}_READDATAVALID f2h_sdram${i}_READDATAVALID f2h_sdram${i}_READ f2h_sdram${i}_READ f2h_sdram${i}_WRITEDATA f2h_sdram${i}_WRITEDATA f2h_sdram${i}_BYTEENABLE f2h_sdram${i}_BYTEENABLE f2h_sdram${i}_WRITE f2h_sdram${i}_WRITE" + } elseif { [string compare $type_choice [F2HSDRAM_AVM_WRITEONLY]] == 0 } { + set type "avalon" + set total_command_port [expr $total_command_port + 1] + if {$type_width == 128} { + set total_write_port [expr $total_write_port + 2] + } elseif {$type_width == 256 } { + set total_write_port [expr $total_write_port + 4] + } else { + set total_write_port [expr $total_write_port + 1] + } + set sdram_data "f2h_sdram${i}_ADDRESS f2h_sdram${i}_ADDRESS f2h_sdram${i}_BURSTCOUNT f2h_sdram${i}_BURSTCOUNT f2h_sdram${i}_WAITREQUEST f2h_sdram${i}_WAITREQUEST f2h_sdram${i}_WRITEDATA f2h_sdram${i}_WRITEDATA f2h_sdram${i}_BYTEENABLE f2h_sdram${i}_BYTEENABLE f2h_sdram${i}_WRITE f2h_sdram${i}_WRITE" + } elseif { [string compare $type_choice [F2HSDRAM_AVM_READONLY]] == 0 } { + set type "avalon" + set total_command_port [expr $total_command_port + 1] + if {$type_width == 128} { + set total_read_port [expr $total_read_port + 2] + } elseif {$type_width == 256 } { + set total_read_port [expr $total_read_port + 4] + } else { + set total_read_port [expr $total_read_port + 1] + } + set sdram_data "f2h_sdram${i}_ADDRESS f2h_sdram${i}_ADDRESS f2h_sdram${i}_BURSTCOUNT f2h_sdram${i}_BURSTCOUNT f2h_sdram${i}_WAITREQUEST f2h_sdram${i}_WAITREQUEST f2h_sdram${i}_READDATA f2h_sdram${i}_READDATA f2h_sdram${i}_READDATAVALID f2h_sdram${i}_READDATAVALID f2h_sdram${i}_READ f2h_sdram${i}_READ" + } else { + set type "axi" + if { [ expr $total_command_port % 2 ] } { + incr total_command_port 1 + } + set total_command_port [expr $total_command_port + 2] + if {$type_width == 128} { + set total_write_port [expr $total_write_port + 2] + set total_read_port [expr $total_read_port + 2] + } elseif {$type_width == 256 } { + set total_write_port [expr $total_write_port + 4] + set total_read_port [expr $total_read_port + 4] + } else { + set total_write_port [expr $total_write_port + 1] + set total_read_port [expr $total_read_port + 1] + } + set sdram_data "f2h_sdram${i}_ARADDR f2h_sdram${i}_ARADDR f2h_sdram${i}_ARLEN f2h_sdram${i}_ARLEN f2h_sdram${i}_ARID f2h_sdram${i}_ARID f2h_sdram${i}_ARSIZE f2h_sdram${i}_ARSIZE f2h_sdram${i}_ARBURST f2h_sdram${i}_ARBURST f2h_sdram${i}_ARLOCK f2h_sdram${i}_ARLOCK f2h_sdram${i}_ARPROT f2h_sdram${i}_ARPROT f2h_sdram${i}_ARVALID f2h_sdram${i}_ARVALID f2h_sdram${i}_ARCACHE f2h_sdram${i}_ARCACHE f2h_sdram${i}_AWADDR f2h_sdram${i}_AWADDR f2h_sdram${i}_AWLEN f2h_sdram${i}_AWLEN f2h_sdram${i}_AWID f2h_sdram${i}_AWID f2h_sdram${i}_AWSIZE f2h_sdram${i}_AWSIZE f2h_sdram${i}_AWBURST f2h_sdram${i}_AWBURST f2h_sdram${i}_AWLOCK f2h_sdram${i}_AWLOCK f2h_sdram${i}_AWPROT f2h_sdram${i}_AWPROT f2h_sdram${i}_AWVALID f2h_sdram${i}_AWVALID f2h_sdram${i}_AWCACHE f2h_sdram${i}_AWCACHE f2h_sdram${i}_BRESP f2h_sdram${i}_BRESP f2h_sdram${i}_BID f2h_sdram${i}_BID f2h_sdram${i}_BVALID f2h_sdram${i}_BVALID f2h_sdram${i}_BREADY f2h_sdram${i}_BREADY f2h_sdram${i}_ARREADY f2h_sdram${i}_ARREADY f2h_sdram${i}_AWREADY f2h_sdram${i}_AWREADY f2h_sdram${i}_RREADY f2h_sdram${i}_RREADY f2h_sdram${i}_RDATA f2h_sdram${i}_RDATA f2h_sdram${i}_RRESP f2h_sdram${i}_RRESP f2h_sdram${i}_RLAST f2h_sdram${i}_RLAST f2h_sdram${i}_RID f2h_sdram${i}_RID f2h_sdram${i}_RVALID f2h_sdram${i}_RVALID f2h_sdram${i}_WLAST f2h_sdram${i}_WLAST f2h_sdram${i}_WVALID f2h_sdram${i}_WVALID f2h_sdram${i}_WDATA f2h_sdram${i}_WDATA f2h_sdram${i}_WSTRB f2h_sdram${i}_WSTRB f2h_sdram${i}_WREADY f2h_sdram${i}_WREADY f2h_sdram${i}_WID f2h_sdram${i}_WID" + } + + if {$total_command_port > 6 || $total_write_port > 4 || $total_read_port > 4} { + break + } + add_interface f2h_sdram${i}_clock clock Input + set_interface_property f2h_sdram${i}_clock EXPORT_OF bridges.f2h_sdram${i}_clock + set_interface_property f2h_sdram${i}_clock PORT_NAME_MAP "f2h_sdram${i}_clk f2h_sdram${i}_clk" + add_interface f2h_sdram${i}_data $type slave + set_interface_property f2h_sdram${i}_data EXPORT_OF bridges.f2h_sdram${i}_data + set_interface_property f2h_sdram${i}_data PORT_NAME_MAP "$sdram_data" + } + + if $bonding_out_signal { + set bon_out_signal "f2h_sdram_BONOUT_1 f2h_sdram_BONOUT_1 f2h_sdram_BONOUT_2 f2h_sdram_BONOUT_2" + add_interface f2h_sdram_bon_out conduit Output + set_interface_property f2h_sdram_bon_out EXPORT_OF bridges.f2h_sdram_bon_out + set_interface_property f2h_sdram_bon_out PORT_NAME_MAP "$bon_out_signal" + } + + } + + set declared_svd_file 0 + set svd_path [file join $::env(QUARTUS_ROOTDIR) .. ip altera hps altera_hps altera_hps.svd] + if { $h2f_present } { + hps_utils_add_slave_interface arm_a9_0.altera_axi_master bridges.axi_h2f {0xc0000000} + if { $number_of_a9 > 1 } { + hps_utils_add_slave_interface arm_a9_1.altera_axi_master bridges.axi_h2f {0xc0000000} + } + + add_interface h2f_axi_clock clock Input + set_interface_property h2f_axi_clock EXPORT_OF bridges.h2f_axi_clock + set_interface_property h2f_axi_clock PORT_NAME_MAP "h2f_axi_clk h2f_axi_clk" + + add_interface h2f_axi_master axi master + set_interface_property h2f_axi_master EXPORT_OF bridges.h2f + set_interface_property h2f_axi_master PORT_NAME_MAP "h2f_AWID h2f_AWID h2f_AWADDR h2f_AWADDR h2f_AWLEN h2f_AWLEN h2f_AWSIZE h2f_AWSIZE h2f_AWBURST h2f_AWBURST h2f_AWLOCK h2f_AWLOCK h2f_AWCACHE h2f_AWCACHE h2f_AWPROT h2f_AWPROT h2f_AWVALID h2f_AWVALID h2f_AWREADY h2f_AWREADY h2f_WID h2f_WID h2f_WDATA h2f_WDATA h2f_WSTRB h2f_WSTRB h2f_WLAST h2f_WLAST h2f_WVALID h2f_WVALID h2f_WREADY h2f_WREADY h2f_BID h2f_BID h2f_BRESP h2f_BRESP h2f_BVALID h2f_BVALID h2f_BREADY h2f_BREADY h2f_ARID h2f_ARID h2f_ARADDR h2f_ARADDR h2f_ARLEN h2f_ARLEN h2f_ARSIZE h2f_ARSIZE h2f_ARBURST h2f_ARBURST h2f_ARLOCK h2f_ARLOCK h2f_ARCACHE h2f_ARCACHE h2f_ARPROT h2f_ARPROT h2f_ARVALID h2f_ARVALID h2f_ARREADY h2f_ARREADY h2f_RID h2f_RID h2f_RDATA h2f_RDATA h2f_RRESP h2f_RRESP h2f_RLAST h2f_RLAST h2f_RVALID h2f_RVALID h2f_RREADY h2f_RREADY" + set_interface_property h2f_axi_master SVD_ADDRESS_GROUP "hps" + set_interface_property h2f_axi_master SVD_ADDRESS_OFFSET 0xC0000000 + if {!$declared_svd_file} { + set_interface_property h2f_axi_master CMSIS_SVD_FILE $svd_path + set declared_svd_file 1 + } + } + + if { $f2h_present } { + add_interface f2h_axi_clock clock Input + set_interface_property f2h_axi_clock EXPORT_OF bridges.f2h_axi_clock + set_interface_property f2h_axi_clock PORT_NAME_MAP "f2h_axi_clk f2h_axi_clk" + + add_interface f2h_axi_slave axi slave + set_interface_property f2h_axi_slave EXPORT_OF bridges.f2h + set_interface_property f2h_axi_slave PORT_NAME_MAP "f2h_AWID f2h_AWID f2h_AWADDR f2h_AWADDR f2h_AWLEN f2h_AWLEN f2h_AWSIZE f2h_AWSIZE f2h_AWBURST f2h_AWBURST f2h_AWLOCK f2h_AWLOCK f2h_AWCACHE f2h_AWCACHE f2h_AWPROT f2h_AWPROT f2h_AWVALID f2h_AWVALID f2h_AWREADY f2h_AWREADY f2h_AWUSER f2h_AWUSER f2h_WID f2h_WID f2h_WDATA f2h_WDATA f2h_WSTRB f2h_WSTRB f2h_WLAST f2h_WLAST f2h_WVALID f2h_WVALID f2h_WREADY f2h_WREADY f2h_BID f2h_BID f2h_BRESP f2h_BRESP f2h_BVALID f2h_BVALID f2h_BREADY f2h_BREADY f2h_ARID f2h_ARID f2h_ARADDR f2h_ARADDR f2h_ARLEN f2h_ARLEN f2h_ARSIZE f2h_ARSIZE f2h_ARBURST f2h_ARBURST f2h_ARLOCK f2h_ARLOCK f2h_ARCACHE f2h_ARCACHE f2h_ARPROT f2h_ARPROT f2h_ARVALID f2h_ARVALID f2h_ARREADY f2h_ARREADY f2h_ARUSER f2h_ARUSER f2h_RID f2h_RID f2h_RDATA f2h_RDATA f2h_RRESP f2h_RRESP f2h_RLAST f2h_RLAST f2h_RVALID f2h_RVALID f2h_RREADY f2h_RREADY" + } + + if { $h2f_lw_present } { + hps_utils_add_slave_interface arm_a9_0.altera_axi_master bridges.axi_h2f_lw {0xff200000} + if { $number_of_a9 > 1 } { + hps_utils_add_slave_interface arm_a9_1.altera_axi_master bridges.axi_h2f_lw {0xff200000} + } + + add_interface h2f_lw_axi_clock clock Input + set_interface_property h2f_lw_axi_clock EXPORT_OF bridges.h2f_lw_axi_clock + set_interface_property h2f_lw_axi_clock PORT_NAME_MAP "h2f_lw_axi_clk h2f_lw_axi_clk" + + add_interface h2f_lw_axi_master axi start + set_interface_property h2f_lw_axi_master EXPORT_OF bridges.h2f_lw + set_interface_property h2f_lw_axi_master PORT_NAME_MAP "h2f_lw_AWID h2f_lw_AWID h2f_lw_AWADDR h2f_lw_AWADDR h2f_lw_AWLEN h2f_lw_AWLEN h2f_lw_AWSIZE h2f_lw_AWSIZE h2f_lw_AWBURST h2f_lw_AWBURST h2f_lw_AWLOCK h2f_lw_AWLOCK h2f_lw_AWCACHE h2f_lw_AWCACHE h2f_lw_AWPROT h2f_lw_AWPROT h2f_lw_AWVALID h2f_lw_AWVALID h2f_lw_AWREADY h2f_lw_AWREADY h2f_lw_WID h2f_lw_WID h2f_lw_WDATA h2f_lw_WDATA h2f_lw_WSTRB h2f_lw_WSTRB h2f_lw_WLAST h2f_lw_WLAST h2f_lw_WVALID h2f_lw_WVALID h2f_lw_WREADY h2f_lw_WREADY h2f_lw_BID h2f_lw_BID h2f_lw_BRESP h2f_lw_BRESP h2f_lw_BVALID h2f_lw_BVALID h2f_lw_BREADY h2f_lw_BREADY h2f_lw_ARID h2f_lw_ARID h2f_lw_ARADDR h2f_lw_ARADDR h2f_lw_ARLEN h2f_lw_ARLEN h2f_lw_ARSIZE h2f_lw_ARSIZE h2f_lw_ARBURST h2f_lw_ARBURST h2f_lw_ARLOCK h2f_lw_ARLOCK h2f_lw_ARCACHE h2f_lw_ARCACHE h2f_lw_ARPROT h2f_lw_ARPROT h2f_lw_ARVALID h2f_lw_ARVALID h2f_lw_ARREADY h2f_lw_ARREADY h2f_lw_RID h2f_lw_RID h2f_lw_RDATA h2f_lw_RDATA h2f_lw_RRESP h2f_lw_RRESP h2f_lw_RLAST h2f_lw_RLAST h2f_lw_RVALID h2f_lw_RVALID h2f_lw_RREADY h2f_lw_RREADY" + set_interface_property h2f_lw_axi_master SVD_ADDRESS_GROUP "hps" + set_interface_property h2f_lw_axi_master SVD_ADDRESS_OFFSET 0xFF200000 + if {!$declared_svd_file} { + set_interface_property h2f_lw_axi_master CMSIS_SVD_FILE $svd_path + set declared_svd_file 1 + } + } + + if {!$declared_svd_file} { + set_module_assignment "cmsis.svd.file" $svd_path + set_module_assignment "cmsis.svd.suffix" "hps" + } + + clocks_logicalview_dtg + + if { $number_of_a9 > 0 } { + hps_utils_add_instance_clk_reset clk_0 arm_a9_0 arm_a9 + } + + if { $number_of_a9 > 1 } { + hps_utils_add_instance_clk_reset clk_0 arm_a9_1 arm_a9 + } + + + hps_instantiate_arm_gic_0 $number_of_a9 + + hps_instantiate_L2 $number_of_a9 + + hps_instantiate_dma $number_of_a9 + + hps_instantiate_sysmgr $number_of_a9 + + hps_instantiate_clkmgr $number_of_a9 + + hps_instantiate_rstmgr $number_of_a9 + + hps_instantiate_fpgamgr $number_of_a9 + + hps_instantiate_uart0 $number_of_a9 "UART0_PinMuxing" [get_parameter_value l4_sp_clk_mhz] + + hps_instantiate_uart1 $number_of_a9 "UART1_PinMuxing" [get_parameter_value l4_sp_clk_mhz] + + hps_instantiate_timer0 $number_of_a9 + + hps_instantiate_timer1 $number_of_a9 + + hps_instantiate_timer2 $number_of_a9 + + hps_instantiate_timer3 $number_of_a9 + + hps_instantiate_wd_timer0 $number_of_a9 + + hps_instantiate_wd_timer1 $number_of_a9 + + hps_instantiate_gpio0 $number_of_a9 + + hps_instantiate_gpio1 $number_of_a9 + + hps_instantiate_gpio2 $number_of_a9 + + hps_instantiate_i2c0 $number_of_a9 "I2C0_PinMuxing" + + hps_instantiate_i2c1 $number_of_a9 "I2C1_PinMuxing" + + hps_instantiate_i2c2 $number_of_a9 "I2C2_PinMuxing" + + hps_instantiate_i2c3 $number_of_a9 "I2C3_PinMuxing" + + hps_instantiate_nand0 $number_of_a9 "NAND_PinMuxing" + + hps_instantiate_spim0 $number_of_a9 "SPIM0_PinMuxing" + + hps_instantiate_spim1 $number_of_a9 "SPIM1_PinMuxing" + + hps_instantiate_qspi $number_of_a9 "QSPI_PinMuxing" + + hps_instantiate_sdmmc $number_of_a9 "SDIO_PinMuxing" + + hps_instantiate_usb0 $number_of_a9 "USB0_PinMuxing" + + hps_instantiate_usb1 $number_of_a9 "USB1_PinMuxing" + + hps_instantiate_gmac0 $number_of_a9 "EMAC0_PinMuxing" + + hps_instantiate_gmac1 $number_of_a9 "EMAC1_PinMuxing" + + hps_instantiate_dcan0 $number_of_a9 "CAN0_PinMuxing" + + hps_instantiate_dcan1 $number_of_a9 "CAN1_PinMuxing" + + hps_instantiate_l3regs $number_of_a9 + + hps_instantiate_sdrctl $number_of_a9 + + hps_instantiate_axi_ocram $number_of_a9 + + hps_instantiate_axi_sdram $number_of_a9 + + hps_instantiate_timer $number_of_a9 + + hps_instantiate_scu $number_of_a9 + + add_connection arm_gic_0.arm_gic_ppi timer.interrupt_sender + set_connection_parameter_value arm_gic_0.arm_gic_ppi/timer.interrupt_sender irqNumber 13 + + if { $f2h_present } { + hps_utils_add_slave_interface bridges.axi_f2h arm_gic_0.axi_slave0 {0xfffed000} + hps_utils_add_slave_interface bridges.axi_f2h arm_gic_0.axi_slave1 {0xfffec100} + hps_utils_add_slave_interface bridges.axi_f2h L2.axi_slave0 {0xfffef000} + hps_utils_add_slave_interface bridges.axi_f2h dma.axi_slave0 {0xffe01000} + hps_utils_add_slave_interface bridges.axi_f2h sysmgr.axi_slave0 {0xffd08000} + hps_utils_add_slave_interface bridges.axi_f2h clkmgr.axi_slave0 {0xffd04000} + hps_utils_add_slave_interface bridges.axi_f2h rstmgr.axi_slave0 {0xffd05000} + hps_utils_add_slave_interface bridges.axi_f2h fpgamgr.axi_slave0 {0xff706000} + hps_utils_add_slave_interface bridges.axi_f2h fpgamgr.axi_slave1 {0xffb90000} + hps_utils_add_slave_interface bridges.axi_f2h uart0.axi_slave0 {0xffc02000} + hps_utils_add_slave_interface bridges.axi_f2h uart1.axi_slave0 {0xffc03000} + hps_utils_add_slave_interface bridges.axi_f2h timer0.axi_slave0 {0xffc08000} + hps_utils_add_slave_interface bridges.axi_f2h timer1.axi_slave0 {0xffc09000} + hps_utils_add_slave_interface bridges.axi_f2h timer2.axi_slave0 [hps_timer2_base] + hps_utils_add_slave_interface bridges.axi_f2h timer3.axi_slave0 [hps_timer3_base] + hps_utils_add_slave_interface bridges.axi_f2h gpio0.axi_slave0 {0xff708000} + hps_utils_add_slave_interface bridges.axi_f2h gpio1.axi_slave0 {0xff709000} + hps_utils_add_slave_interface bridges.axi_f2h gpio2.axi_slave0 {0xff70a000} + hps_utils_add_slave_interface bridges.axi_f2h i2c0.axi_slave0 {0xffc04000} + hps_utils_add_slave_interface bridges.axi_f2h i2c1.axi_slave0 {0xffc05000} + hps_utils_add_slave_interface bridges.axi_f2h i2c2.axi_slave0 {0xffc06000} + hps_utils_add_slave_interface bridges.axi_f2h i2c3.axi_slave0 {0xffc07000} + hps_utils_add_slave_interface bridges.axi_f2h nand0.axi_slave0 {0xff900000} + hps_utils_add_slave_interface bridges.axi_f2h nand0.axi_slave1 {0xffb80000} + hps_utils_add_slave_interface bridges.axi_f2h spim0.axi_slave0 [hps_spim0_base] + hps_utils_add_slave_interface bridges.axi_f2h spim1.axi_slave0 [hps_spim1_base] + hps_utils_add_slave_interface bridges.axi_f2h qspi.axi_slave0 {0xff705000} + hps_utils_add_slave_interface bridges.axi_f2h qspi.axi_slave1 {0xffa00000} + hps_utils_add_slave_interface bridges.axi_f2h sdmmc.axi_slave0 {0xff704000} + hps_utils_add_slave_interface bridges.axi_f2h usb0.axi_slave0 {0xffb00000} + hps_utils_add_slave_interface bridges.axi_f2h usb1.axi_slave0 {0xffb40000} + hps_utils_add_slave_interface bridges.axi_f2h gmac0.axi_slave0 {0xff700000} + hps_utils_add_slave_interface bridges.axi_f2h gmac1.axi_slave0 {0xff702000} + hps_utils_add_slave_interface bridges.axi_f2h axi_ocram.axi_slave0 {0xffff0000} + hps_utils_add_slave_interface bridges.axi_f2h axi_sdram.axi_slave0 [hps_sdram_base] + hps_utils_add_slave_interface bridges.axi_f2h timer.axi_slave0 {0xfffec600} + hps_utils_add_slave_interface bridges.axi_f2h dcan0.axi_slave0 [hps_dcan0_base] + hps_utils_add_slave_interface bridges.axi_f2h dcan1.axi_slave0 [hps_dcan1_base] + hps_utils_add_slave_interface bridges.axi_f2h l3regs.axi_slave0 [hps_l3regs_base] + hps_utils_add_slave_interface bridges.axi_f2h sdrctl.axi_slave0 [hps_sdrctl_base] + } + + ##### F2H ##### + if [is_enabled F2SINTERRUPT_Enable] { + set any_interrupt_enabled 1 + set iname "f2h_irq" + set pname "f2h_irq" + add_interface "${iname}0" interrupt receiver + set_interface_property f2h_irq0 EXPORT_OF arm_gic_0.f2h_irq_0_irq_rx_offset_40 + set_interface_property f2h_irq0 PORT_NAME_MAP "f2h_irq_p0 irq_siq_40" + + add_interface "${iname}1" interrupt receiver + set_interface_property f2h_irq1 EXPORT_OF arm_gic_0.f2h_irq_32_irq_rx_offset_72 + set_interface_property f2h_irq1 PORT_NAME_MAP "f2h_irq_p1 irq_siq_72" + } +} + +set_module_property OPAQUE_ADDRESS_MAP false +set_module_property STRUCTURAL_COMPOSITION_CALLBACK compose_logicalview +proc compose_logicalview {} { + # synchronize device families between the EMIF and HPS parameter sets + set_parameter_value hps_device_family [get_parameter_value SYS_INFO_DEVICE_FAMILY] + fpga_interfaces::init + fpga_interfaces::set_bfm_types [array get DB_bfm_types] + + hps_io::init + validate + elab 1 + + update_hps_to_fpga_clock_frequency_parameters + + + fpga_interfaces::serialize fpga_interfaces_data + + add_instance fpga_interfaces altera_interface_generator + set_instance_parameter_value fpga_interfaces interfaceDefinition [array get fpga_interfaces_data] + + expose_border fpga_interfaces $fpga_interfaces_data(interfaces) + + #declare_cmsis_svd $fpga_interfaces_data(interfaces) + + logicalview_dtg +} + +proc declare_cmsis_svd {interfaces_str} { + array set interfaces $interfaces_str + set interface_names $interfaces([ORDERED_NAMES]) + + set h2f_exists 0 + set lwh2f_exists 0 + foreach interface_name $interface_names { + if {[string compare $interface_name "h2f_axi_master"] == 0} { + set h2f_exists 1 + } elseif {[string compare $interface_name "h2f_lw_axi_master"] == 0} { + set lwh2f_exists 1 + } + } + + set svd_path [file join $::env(QUARTUS_ROOTDIR) .. ip altera hps altera_hps altera_hps.svd] + set address_group hps + set declared_svd_file 0 + + if {$h2f_exists} { + if {!$declared_svd_file} { + set_interface_property h2f_axi_master CMSIS_SVD_FILE $svd_path + set declared_svd_file 1 + } + set_interface_property h2f_axi_master SVD_ADDRESS_GROUP $address_group + set_interface_property h2f_axi_master SVD_ADDRESS_OFFSET 0xC0000000 + } + if {$lwh2f_exists} { + if {!$declared_svd_file} { + set_interface_property h2f_lw_axi_master CMSIS_SVD_FILE $svd_path + set declared_svd_file 1 + } + set_interface_property h2f_lw_axi_master SVD_ADDRESS_GROUP $address_group + set_interface_property h2f_lw_axi_master SVD_ADDRESS_OFFSET 0xFF200000 + } + if {!$declared_svd_file} { + set_module_assignment "cmsis.svd.file" $svd_path + set_module_assignment "cmsis.svd.suffix" $address_group + } +} + + +###################### +##### Validation ##### +###################### + +proc validate {} { + set device_family [get_parameter_value hps_device_family] + set device [get_device] + ensure_pin_muxing_data $device_family + update_table_derived_parameters + + validate_F2SDRAM + update_S2F_CLK_mux_options + update_pin_muxing_ui $device_family + + # funset placement_by_pin + validate_pin_muxing $device_family placement_by_pin + update_gpio_ui placement_by_pin + + validate_TEST + + validate_interrupt $device_family + + validate_clocks + +} + +proc validate_TEST {} { + set ini [get_parameter_value quartus_ini_hps_ip_enable_test_interface] + set_parameter_property TEST_Enable visible $ini +} + +proc hide_param { paramName hide} { + +} +proc update_hps_to_fpga_clock_frequency_parameters {} { + set u0 [get_parameter_value S2FCLK_USER0CLK_Enable] + set u1 [get_parameter_value S2FCLK_USER1CLK_Enable] + #set u2 [get_parameter_value S2FCLK_USER2CLK_Enable] + + for { set i 0 } { $i < 2 } { incr i } { + set_parameter_property "S2FCLK_USER${i}CLK_FREQ" enabled [expr "\$u${i}"] + + if { [string compare true [expr "\$u${i}"] ] == 0 } { + fpga_interfaces::set_interface_property "h2f_user${i}_clock" clockRateKnown true + fpga_interfaces::set_interface_property "h2f_user${i}_clock" clockRate [expr [get_parameter_value "S2FCLK_USER${i}CLK_FREQ"] * 1000000 ] + } + } +} + +proc update_table_derived_parameters {} { + update_f2sdram_names + update_dma_peripheral_ids +} + +proc update_f2sdram_names {} { + set num_rows [llength [get_parameter_value F2SDRAM_Width]] + set names [list] + + for {set index 0} {$index < $num_rows} {incr index} { + set name "f2h_sdram${index}" + lappend names $name + } + set_parameter_value F2SDRAM_Name_DERIVED ${names} +} + +proc update_dma_peripheral_ids {} { + set periph_id_list {0 1 2 3 4 5 6 7} + set_parameter_value DMA_PeriphId_DERIVED $periph_id_list +} + +proc is_enabled {parameter} { + if { [string compare [get_parameter_value $parameter] "true" ] == 0 } { + return 1 + } else { + return 0 + } +} + +proc validate_F2SDRAM {} { + set type_list [get_parameter_value F2SDRAM_Type] + set width_list [get_parameter_value F2SDRAM_Width] + set rows [llength $width_list] + + set command_ports_bit 0 + set read_ports_bit 0 + set write_ports_bit 0 + + set command_ports_mask 0 + set read_ports_mask 0 + set write_ports_mask 0 + set reset_ports_mask 0 + + for {set index 0} {${index} < ${rows}} {incr index} { + # check for invalid combinations of type/width + set mytype [lindex $type_list $index] + set mywidth [lindex $width_list $index] + + if {$mywidth < 64} { + send_message warning "Setting the slave port width of interface f2h_sdram${index} to ${mywidth} results in bandwidth under-utilization. Altera recommends you set the interface data width to 64-bit or greater." + } + + # count used ports + # command + if { [string compare $mytype [F2HSDRAM_AXI3]] == 0 } { + if { [ expr $command_ports_bit % 2 ] } { + incr command_ports_bit 1 + } + set command_ports_mask [ expr $command_ports_mask | ( 3 << $command_ports_bit) ] + incr command_ports_bit 2 + } else { + set command_ports_mask [ expr $command_ports_mask | ( 1 << $command_ports_bit) ] + incr command_ports_bit 1 + } + + # read + if {$mytype != [F2HSDRAM_AVM_WRITEONLY]} { + if {$mywidth <= 64} { + set read_ports_mask [ expr $read_ports_mask | ( 1 << $read_ports_bit) ] + incr read_ports_bit 1 + } elseif {$mywidth == 128} { + set read_ports_mask [ expr $read_ports_mask | ( 3 << $read_ports_bit) ] + incr read_ports_bit 2 + } else { + set read_ports_mask [ expr $read_ports_mask | ( 15 << $read_ports_bit) ] + incr read_ports_bit 4 + } + } + + # write + if {$mytype != [F2HSDRAM_AVM_READONLY]} { + if {$mywidth <= 64} { + set write_ports_mask [ expr $write_ports_mask | ( 1 << $write_ports_bit) ] + incr write_ports_bit 1 + } elseif {$mywidth == 128} { + set write_ports_mask [ expr $write_ports_mask | ( 3 << $write_ports_bit) ] + incr write_ports_bit 2 + } else { + set write_ports_mask [ expr $write_ports_mask | ( 15 << $write_ports_bit) ] + incr write_ports_bit 4 + } + } + + # reset + set reset_ports_mask [ expr ($command_ports_mask << 8) | ($write_ports_mask << 4) | ($read_ports_mask) ] + + } + # check for port over-use + if {$command_ports_bit > 6} { + send_message error "The current FPGA to SDRAM configuration is using more command ports than are available." + } + if {$read_ports_bit > 4} { + send_message error "The current FPGA to SDRAM configuration is using more read ports than are available." + } + if {$write_ports_bit > 4} { + send_message error "The current FPGA to SDRAM configuration is using more write ports than are available." + } + + # Store ports used & number of elements to determine when new rows are added + set_parameter_value F2SDRAM_Width_Last_Size $rows + set_parameter_value F2SDRAM_CMD_PORT_USED [ format "0x%X" $command_ports_mask ] + set_parameter_value F2SDRAM_RD_PORT_USED [ format "0x%X" $read_ports_mask ] + set_parameter_value F2SDRAM_WR_PORT_USED [ format "0x%X" $write_ports_mask ] + set_parameter_value F2SDRAM_RST_PORT_USED [ format "0x%X" $reset_ports_mask ] + + # Bonding_out signals will be exported if f2sdram selected + if { ${rows} > 0 } { + set param [get_parameter_value quartus_ini_hps_ip_f2sdram_bonding_out] + set_parameter_property BONDING_OUT_ENABLED visible $param + set_parameter_property BONDING_OUT_ENABLED enabled $param + } else { + set_parameter_property BONDING_OUT_ENABLED enabled false + } + +} + +proc update_S2F_CLK_mux_options {} { + # TODO: retrieve mux options + # TODO: set allowed_ranges on muxes +} + +proc dec2bin {i} { + set res {} + while {$i>0} { + set res [ expr {$i%2} ]$res + set i [expr {$i/2}] + } + if {$res == {}} { + set res 0 + } + return $res +} + +##################################################################### +# +# Gets valid modes for a peripheral with a given pin muxing option. +# Parameters: * peripheral_ref: name of an array pointing to the +# Peripheral HPS I/O Data +# +# Update parameter value with label +proc get_valid_modes {peripheral_name pin_muxing_option peripheral_ref fpga_available} { +##################################################################### + upvar 1 $peripheral_ref peripheral + + if {[info exists peripheral(pin_sets)]} { + array set pin_sets $peripheral(pin_sets) + } + + if {[info exists pin_sets($pin_muxing_option)]} { + array set pin_set $pin_sets($pin_muxing_option) + set pin_set_modes $pin_set(valid_modes) + if {[string match -nocase "trace" $peripheral_name]} { + set valid_modes [list "HPS:8-bit Data" "HPSx4:4-bit Data"] + } elseif {[string match -nocase "usb*" $peripheral_name]} { + set valid_modes [list "SDR:SDR with PHY clock output mode" "SDR without external clock:SDR with PHY clock input mode"] + } else { + set valid_modes [lsort -ascii -increasing $pin_set_modes] + } + } elseif {$fpga_available && [string compare $pin_muxing_option [FPGA_MUX_VALUE]] == 0} { + set valid_modes [list "Full"] + } else { + set valid_modes [list [NA_MODE_VALUE]] + } + return $valid_modes +} + +proc is_peripheral_low_speed_serial_interface {peripheral_name} { + if {[string match -nocase "i2c*" $peripheral_name] || + [string match -nocase "can*" $peripheral_name] || + [string match -nocase "spi*" $peripheral_name] || + [string match -nocase "uart*" $peripheral_name] + } { + return 1 + } + return 0 +} + +# updates the _PinMuxing and _Mode parameter allowed ranges +# -uses a data structure to keep track of choices +# -allowed ranges can come from FPGA Peripheral Interfaces or IOs +# -when a pin muxing option is selected, the mode allowed ranges are +# set according to what's specified from the source (FPGA or pin i/o) +proc update_pin_muxing_ui {device_family} { + + set peripheral_names [list_peripheral_names] + foreach peripheral $peripheral_names { + + get_peripheral_parameter_valid_ranges hps_ip_pin_muxing_model $peripheral\ + selected_pin_muxing_option pin_muxing_options mode_options + + set pin_muxing_param_name [format [PIN_MUX_PARAM_FORMAT] $peripheral] + set mode_param_name [format [MODE_PARAM_FORMAT] $peripheral] + + set pin_muxing_options [lsort -ascii $pin_muxing_options] + set pin_muxing_options [linsert $pin_muxing_options 0 [UNUSED_MUX_VALUE]] + set_parameter_property $pin_muxing_param_name enabled true + set_parameter_property $pin_muxing_param_name visible true + set_parameter_property $pin_muxing_param_name allowed_ranges $pin_muxing_options + set_parameter_property $mode_param_name visible true + + + set selected_mode_option [get_parameter_value $mode_param_name] + + # Disable I2C parameters so they can only be changed by altering EMAC parameters + # in the HPS IP GUI + if {([string compare $peripheral "I2C2" ] == 0 || [string compare $peripheral "I2C3" ] == 0) + && [string match "*EMAC*" $selected_mode_option]} { + set_parameter_property $pin_muxing_param_name enabled false + set_parameter_property $mode_param_name enabled false + } else { + set_parameter_property $mode_param_name enabled true + } + set_parameter_property $mode_param_name allowed_ranges $mode_options + + # Disabled peripherals that not supported by certain device family + if {[check_device_family_equivalence $device_family ARRIAV]} { + foreach excluded_peripheral [ARRIAV_EXCLUDED_PERIPHRERALS] { + if {[string compare $excluded_peripheral $peripheral] == 0} { + set_parameter_property $pin_muxing_param_name enabled false + set_parameter_property $pin_muxing_param_name visible false + set_parameter_property $mode_param_name enabled false + set_parameter_property $mode_param_name visible false + } + } + } + } + + # Only show I2C's "Used by EMACx" modes when EMAC is using I2C + if {[is_pin_mux_data_available hps_ip_pin_muxing_model]} { + foreach emac {EMAC0 EMAC1} { + set emac_pin_set [get_parameter_value [format [PIN_MUX_PARAM_FORMAT] $emac]] + set emac_mode [get_parameter_value [format [MODE_PARAM_FORMAT] $emac]] + + funset i2c_name + get_linked_peripheral hps_ip_pin_muxing_model $emac $emac_pin_set\ + i2c_name i2c_pin_set i2c_mode + + if {[info exists i2c_name] && ![string match "*${i2c_name}*" $emac_mode]} { + # remove EMAC mode + set i2c_mode_param [format [MODE_PARAM_FORMAT] $i2c_name] + set i2c_valid_modes [get_parameter_property $i2c_mode_param ALLOWED_RANGES] + + set new_i2c_valid_modes [list] + foreach mode $i2c_valid_modes { + if {![string match "*${emac}*" $mode]} { + lappend new_i2c_valid_modes $mode + } + } + set_parameter_property $i2c_mode_param ALLOWED_RANGES $new_i2c_valid_modes + } + } + } +} + +proc validate_interrupt {device_family} { + set interrupt_groups [list_h2f_interrupt_groups] + set excluded "CAN" + foreach interrupt_group $interrupt_groups { + set parameter "S2FINTERRUPT_${interrupt_group}_Enable" + set_parameter_property $parameter enabled true + set_parameter_property $parameter visible true + if {[check_device_family_equivalence $device_family ARRIAV] && [string compare $excluded $interrupt_group] == 0} { + set_parameter_property $parameter enabled false + set_parameter_property $parameter visible false + } + } +} + +proc update_gpio_ui {placement_by_pin_ref} { + upvar 1 $placement_by_pin_ref placement_by_pin + # TODO: caching of what needs to be updated? + set customer_pin_names [list] + set gpio_names [list] + set loanio_names [list] + set conflicts [list] + + set customer_pin_names [hps_ip_pin_muxing_model::get_customer_pin_names] + + foreach_gpio_entry hps_ip_pin_muxing_model\ + entry gpio_index gpio_name pin gplin_used gplin_select\ + { + lappend gpio_names $gpio_name + + set conflict "" + if {[info exists placement_by_pin($pin)]} { + set conflict [join $placement_by_pin($pin) ", "] + } + lappend conflicts $conflict + } + foreach_loan_io_entry hps_ip_pin_muxing_model\ + entry loanio_index loanio_name pin gplin_used gplin_select\ + { + lappend loanio_names $loanio_name + } + set_parameter_value Customer_Pin_Name_DERIVED $customer_pin_names + set_parameter_value GPIO_Name_DERIVED $gpio_names + set_parameter_value LOANIO_Name_DERIVED $loanio_names + set_parameter_value GPIO_Conflict_DERIVED $conflicts +} + +proc peripheral_to_wys_atom_name {device_family peripheral} { + set generic_atom_name [hps_io_peripheral_to_generic_atom_name $peripheral] + set wys_atom_name [generic_atom_to_wys_atom $device_family $generic_atom_name] + return $wys_atom_name +} + +# TODO: deal with going out of bounds (gpio_index > 70) +proc gpio_index_to_gpio_port_index {gpio_index} { + set group [expr {$gpio_index / 29}] + set port_index [expr {$gpio_index % 29}] + + set result [list $group $port_index] + return $result +} + + + +proc validate_pin_muxing {device_family placement_by_pin_ref} { + upvar 1 $placement_by_pin_ref placement_by_pin + + # see which pins are being used more than once + # peripherals + funset pin_to_peripheral ;# pin names to peripheral that is occupying + funset conflict_pin_list ; + + foreach peripheral_name [list_peripheral_names] { + set pins_used 0 + set mapping_msg "Peripheral $peripheral_name pin mapping:" + set comma " " + set periph_inst [string tolower "${peripheral_name}_inst"] + foreach_used_peripheral_pin hps_ip_pin_muxing_model $peripheral_name\ + signal_name\ + map\ + pin\ + location\ + mux_select\ + { + # Validate + set entry_exists [info exists pin_to_peripheral($pin)] + if {$entry_exists == 1} { + set conflicting_peripheral $pin_to_peripheral($pin) + # only emit an error once per unique pair of conflicting peripherals + if {[info exists known_conflicts($conflicting_peripheral)] == 0} { + set known_conflicts($conflicting_peripheral) 1 + # TODO: more detailed error message e.g. which pins? explicitly say the bank and modes? + send_message error "Refer to the Peripherals Mux Table for more details. The selected peripherals '$conflicting_peripheral' and '$peripheral_name' are conflicting. " + } + set conflict_pin_list($pin) 1 + } else { + set pin_to_peripheral($pin) $peripheral_name + } + + # Render pins + lassign $map in_port out_port oe_port + set goes_out 0 + set goes_in 0 + + # by default, all signals are assumed to be from the same instance + if {$in_port != ""} { + set in_port "${periph_inst}:${in_port}" + set goes_in 1 + } + if {$out_port != ""} { + set out_port "${periph_inst}:${out_port}" + set goes_out 1 + } + if {$oe_port != ""} { + set oe_port "${periph_inst}:${oe_port}" + set goes_out 1 + } + + if {$goes_in && $goes_out} { + set dir bidir + } elseif {$goes_out} { + set dir output + } else { + set dir input + } + + hps_io::add_pin $periph_inst $signal_name $dir $location $in_port $out_port $oe_port + + if {[info exists placement_by_pin($pin)] == 0} { + set placement_by_pin($pin) [list] + } + lappend placement_by_pin($pin) "${peripheral_name}.${signal_name}" + + set mapping_msg "${mapping_msg}${comma}${signal_name}:${pin}" + set comma ", " + set pins_used 1 + } + if {$pins_used} { + # send_message info $mapping_msg + set wys_atom_name [peripheral_to_wys_atom_name $device_family $peripheral_name] + set location [locations::get_hps_io_peripheral_location $peripheral_name] + hps_io::add_peripheral ${periph_inst} $wys_atom_name $location + } + } + + # HLGPI input only pins + set hlgpi_pins [hps_ip_pin_muxing_model::get_hlgpi_pins] + set hlgpi_count [llength $hlgpi_pins] + set wys_atom_name [peripheral_to_wys_atom_name $device_family "GPIO"] + set periph_inst "gpio_inst" + set gpio_unused 1 + set device [get_device] + + if { [ string range $device 0 3 ] == "5CSE" && [ string range $device 8 9 ] == "19" } { + send_message info "HLGPI is not available for Device $device (484 pins)" + set_parameter_property HLGPI_Enable enabled false + } else { + set_parameter_property HLGPI_Enable enabled true + } + + if { [is_enabled HLGPI_Enable] && [get_parameter_property HLGPI_Enable enabled] } { + for {set hlgpi_pin_index 0} {$hlgpi_pin_index < $hlgpi_count} {incr hlgpi_pin_index} { + # HLGPI connected to gpio[26:13] + set gpio_port_index [ expr {$hlgpi_pin_index + 13} ] + set hlgpi_pin [ lindex $hlgpi_pins $hlgpi_pin_index] + + if {$gpio_unused} { + set atom_location [locations::get_hps_io_peripheral_location "GPIO"] + hps_io::add_peripheral ${periph_inst} $wys_atom_name $atom_location + set gpio_unused 0 + } + + set signal_name "HLGPI${hlgpi_pin_index}" + set pin_location [::pin_mux_db::get_location_of_pin $hlgpi_pin] + set in_port "${periph_inst}:GPIO2_PORTA_I($gpio_port_index:$gpio_port_index)" + set out_port "" + set oe_port "" + + hps_io::add_pin ${periph_inst} $signal_name input $pin_location $in_port $out_port $oe_port + } + } + + # gpio + funset gpio_port_placement_set ;# set of gpio ports that are being used + set enable_list [get_parameter_value GPIO_Enable] + set wys_atom_name [peripheral_to_wys_atom_name $device_family "GPIO"] + set periph_inst "gpio_inst" + + # check and set GPIO_Pin_Used_DERIVED parameter + set_parameter_value GPIO_Pin_Used_DERIVED false + + foreach_gpio_entry hps_ip_pin_muxing_model\ + entry gpio_index gpio_name pin gplin_used gplin_select\ + { + set enabled 0 + set enable_value [lindex $enable_list $entry] + if { [string compare $enable_value "Yes" ] == 0 } { + set enabled 1 + } + if {$enabled} { + set entry_exists [info exists pin_to_peripheral($pin)] + if {$entry_exists} { + set conflicting_peripheral $pin_to_peripheral($pin) + send_message error "Refer to the Peripherals Mux Table for more details. The selected peripheral '$conflicting_peripheral' and '${gpio_name}' are conflicting." + set conflict_pin_list($pin) 1 + } else { + set pin_to_peripheral($pin) $gpio_name + } + + if {[info exists gpio_port_placement_set($gpio_index)]} { + send_message error "Refer to the Peripherals Mux Table for more details. GPIO${gpio_index} cannot be used twice." + set conflict_pin_list($pin) 1 + } else { + set gpio_port_placement_set($gpio_index) 1 + } + + if {$gpio_unused} { + set atom_location [locations::get_hps_io_peripheral_location "GPIO"] + hps_io::add_peripheral ${periph_inst} $wys_atom_name $atom_location + set gpio_unused 0 + } + + lassign [gpio_index_to_gpio_port_index $gpio_index] gpio_group gpio_port_index + set in_port "${periph_inst}:GPIO${gpio_group}_PORTA_I($gpio_port_index:$gpio_port_index)" + set out_port "${periph_inst}:GPIO${gpio_group}_PORTA_O($gpio_port_index:$gpio_port_index)" + set oe_port "${periph_inst}:GPIO${gpio_group}_PORTA_OE($gpio_port_index:$gpio_port_index)" + + set pin_location [::pin_mux_db::get_location_of_pin $pin] + hps_io::add_pin $periph_inst $gpio_name bidir $pin_location $in_port $out_port $oe_port + + # set GPIO_Pin_Used_DERIVED to true if GPIO pins used + set_parameter_value GPIO_Pin_Used_DERIVED true + } + } + + # loan i/o + set enable_list [get_parameter_value LOANIO_Enable] + set loanio_used 0 + set loanio_count 0 + foreach_loan_io_entry hps_ip_pin_muxing_model\ + entry loanio_index loanio_name pin gplin_used gplin_select\ + { + if {$loanio_count < $loanio_index} { + set loanio_count $loanio_index + } + set enabled 0 + set enable_value [lindex $enable_list $entry] + if { [string compare $enable_value "Yes" ] == 0 } { + set enabled 1 + } + + if {$enabled} { + set entry_exists [info exists pin_to_peripheral($pin)] + if {$entry_exists} { + set conflicting_peripheral $pin_to_peripheral($pin) + send_message error "Refer to the Peripherals Mux Table for more details. The selected peripheral for '$conflicting_peripheral' and '${loanio_name}' are conflicting." + set conflict_pin_list($pin) 1 + } else { + set pin_to_peripheral($pin) $loanio_name + } + + if {[info exists gpio_port_placement_set($loanio_index)]} { + send_message error "Refer to the Peripherals Mux Table for more details. GPIO${loanio_index} cannot be used twice." + set conflict_pin_list($pin) 1 + } else { + set gpio_port_placement_set($loanio_index) 1 + } + + set loanio_used 1 + if {$gpio_unused} { + set atom_location [locations::get_hps_io_peripheral_location "GPIO"] + hps_io::add_peripheral ${periph_inst} $wys_atom_name $atom_location + set gpio_unused 0 + } + + lassign [gpio_index_to_gpio_port_index $loanio_index] gpio_group gpio_port_index + set in_port "${periph_inst}:GPIO${gpio_group}_PORTA_I($gpio_port_index:$gpio_port_index)" + set out_port "${periph_inst}:GPIO${gpio_group}_PORTA_O($gpio_port_index:$gpio_port_index)" + set oe_port "${periph_inst}:GPIO${gpio_group}_PORTA_OE($gpio_port_index:$gpio_port_index)" + + set pin_location [::pin_mux_db::get_location_of_pin $pin] + hps_io::add_pin $periph_inst $loanio_name bidir $pin_location $in_port $out_port $oe_port + + } + } + incr loanio_count ;# count is one greater than the highest index + if $loanio_used { + set wys_atom_name [peripheral_to_wys_atom_name $device_family "LOANIO"] + set location {} + set periph_inst "loan_io_inst" + set iface_name "h2f_loan_io" + set z "h2f_loan_" + fpga_interfaces::add_module_instance ${periph_inst} $wys_atom_name $location + fpga_interfaces::add_interface $iface_name conduit Input + set pin_muxing [get_parameter_value pin_muxing] + fpga_interfaces::add_interface_port $iface_name "${z}in" in Output ${loanio_count} $periph_inst loanio_in + fpga_interfaces::add_interface_port $iface_name "${z}out" out Input ${loanio_count} $periph_inst loanio_out + fpga_interfaces::add_interface_port $iface_name "${z}oe" oe Input ${loanio_count} $periph_inst loanio_oe + + # add loanIO to GPIO atom connection + set loanio_periph_inst "loan_io_inst" + set loanio_iface_name "loanio_gpio" + set loanio_z "loanio_gpio_" + set gpio_periph_inst "gpio_inst" + set gpio_iface_name "gpio_loanio" + set gpio_z "gpio_loanio_" + set gpio_port_size 29 + set start_index 0 + + if {$gpio_unused} { + set gpio_wys_atom_name [peripheral_to_wys_atom_name $device_family "GPIO"] + set gpio_atom_location [locations::get_hps_io_peripheral_location "GPIO"] + hps_io::add_peripheral ${gpio_periph_inst} ${gpio_wys_atom_name} ${gpio_atom_location} + set gpio_unused 0 + } + + fpga_interfaces::add_interface $loanio_iface_name conduit Input "NO_EXPORT" + ::hps_io::internal::add_interface $gpio_iface_name conduit Output "NO_EXPORT" + + for {set i 0} {$i <= 2} {incr i} { + if {[expr ($loanio_count - $start_index)] < $gpio_port_size} { + set gpio_port_size [expr ($loanio_count - $start_index)] + } + set end_index [expr ($start_index + $gpio_port_size - 1)] + + fpga_interfaces::add_interface_port $loanio_iface_name "${loanio_z}loanio${i}_i" "loanio${i}_i" Input ${gpio_port_size} + fpga_interfaces::add_interface_port $loanio_iface_name "${loanio_z}loanio${i}_oe" "loanio${i}_oe" Output ${gpio_port_size} + fpga_interfaces::add_interface_port $loanio_iface_name "${loanio_z}loanio${i}_o" "loanio${i}_o" Output ${gpio_port_size} + + fpga_interfaces::set_port_fragments $loanio_iface_name "${loanio_z}loanio${i}_i" "${loanio_periph_inst}:GPIO_IN($end_index:$start_index)" + fpga_interfaces::set_port_fragments $loanio_iface_name "${loanio_z}loanio${i}_oe" "${loanio_periph_inst}:GPIO_OE($end_index:$start_index)" + fpga_interfaces::set_port_fragments $loanio_iface_name "${loanio_z}loanio${i}_o" "${loanio_periph_inst}:GPIO_OUT($end_index:$start_index)" + + ::hps_io::internal::add_interface_port $gpio_iface_name "${gpio_z}loanio${i}_i" "loanio${i}_i" Output ${gpio_port_size} $gpio_periph_inst "LOANIO${i}_I" + ::hps_io::internal::add_interface_port $gpio_iface_name "${gpio_z}loanio${i}_oe" "loanio${i}_oe" Input ${gpio_port_size} $gpio_periph_inst "LOANIO${i}_OE" + ::hps_io::internal::add_interface_port $gpio_iface_name "${gpio_z}loanio${i}_o" "loanio${i}_o" Input ${gpio_port_size} $gpio_periph_inst "LOANIO${i}_O" + + set start_index [expr ($end_index + 1)] + } + } + set conflicts [list] + set pins [list] + foreach_gpio_entry hps_ip_pin_muxing_model\ + entry gpio_index gpio_name pin gplin_used gplin_select\ + { + set entry_exists [info exists conflict_pin_list($pin)] + if {$entry_exists} { + set conflict "Yes" + } else { + set conflict "No" + } + lappend conflicts $conflict + lappend pins $pin + } + set_parameter_value JAVA_CONFLICT_PIN $conflicts + set_parameter_value JAVA_GUI_PIN_LIST $pins +} + +##################################################### +# +# Sets a valid mode for the peripheral when its pin +# muxing option changes. Will try to retain the +# original mode if available. +# +proc on_altered_peripheral_pin_muxing {peripheral_name} { +##################################################### + set mode_param_name "${peripheral_name}_Mode" + set mode_option [get_parameter_value $mode_param_name] + + get_peripheral_parameter_valid_ranges hps_ip_pin_muxing_model $peripheral_name\ + selected_pin_muxing_option pin_muxing_options new_valid_modes + + # filter the label name of the parameter value if exist + if {[lsearch $new_valid_modes $mode_option] == -1} { + regsub ":.*" [lindex $new_valid_modes 0] "" new_mode_option + } else { + set new_mode_option $mode_option + } + set_parameter_value $mode_param_name $new_mode_option + + if {[string match "*EMAC*" $peripheral_name]} { + on_emac_mode_switch_internal $peripheral_name + } +} + +# Adds the pin muxing model argument +proc on_emac_mode_switch_internal {peripheral_name} { + on_emac_mode_switch hps_ip_pin_muxing_model $peripheral_name +} + +proc validate_and_update_ddr {} { + set desired_operational_freq [get_parameter_value DDR_DesiredFreq] + if {$desired_operational_freq < 0.0} { + send_message error "The operational frequency of the DDR Controller cannot be negative." + } else { + send_message warning "The recommended DDR Controller clock frequency and phase shift information is not correct." + + set_parameter_value DDR_PLLC0RecommendedFreq_DERIVED $desired_operational_freq + set_parameter_value DDR_PLLC1RecommendedFreq_DERIVED [expr $desired_operational_freq * 2.0] + set_parameter_value DDR_PLLC2RecommendedFreq_DERIVED $desired_operational_freq + set_parameter_value DDR_PLLC3RecommendedFreq_DERIVED $desired_operational_freq + + set_parameter_value DDR_PLLC0RecommendedPhase_DERIVED 0.0 + set_parameter_value DDR_PLLC1RecommendedPhase_DERIVED 1.0 + set_parameter_value DDR_PLLC2RecommendedPhase_DERIVED 2.0 + set_parameter_value DDR_PLLC3RecommendedPhase_DERIVED 3.0 + } + + for {set index 0} {${index} < 4} {incr index} { + set p_name "DDR_PLLC${index}ActualFreq" + set value [get_parameter_value $p_name] + if {$value < 0.0} { + send_message error "DDR PLL Output C${index} cannot have a negative clock frequency." + } + + set p_name "DDR_PLLC${index}ActualPhase" + set value [get_parameter_value $p_name] + if {$value < 0.0} { + send_message error "DDR PLL Output C${index} cannot have a negative clock phase shift." + } + } +} + + +###################### +##### Elaboration ##### +###################### + +proc elab {logical_view} { + # TODO: add RTL information for each + set device_family [get_parameter_value hps_device_family] + + elab_clocks_resets $device_family + + elab_MPU_EVENTS $device_family + elab_DEBUGAPB $device_family + elab_STM $device_family + elab_CTI $device_family + elab_TPIUFPGA $device_family + elab_GP $device_family + elab_BOOTFROMFPGA $device_family + + if {$logical_view == 0} { + elab_F2S $device_family + elab_LWH2F $device_family + elab_S2F $device_family + elab_F2SDRAM $device_family + + } + + elab_DMA $device_family + elab_INTERRUPTS $device_family $logical_view + + elab_emac_ptp $device_family + + elab_TEST $device_family + + # Handle Special Case EMAC signal... ptp_ref_clk + set emac0_pin_mux_param_name [format [PIN_MUX_PARAM_FORMAT] EMAC0] + set emac1_pin_mux_param_name [format [PIN_MUX_PARAM_FORMAT] EMAC1] + set emac0_pin_mux_value [get_parameter_value $emac0_pin_mux_param_name] + set emac1_pin_mux_value [get_parameter_value $emac1_pin_mux_param_name] + set emac0_pin_mux_allowed_ranges [get_parameter_property $emac0_pin_mux_param_name allowed_ranges] + set emac1_pin_mux_allowed_ranges [get_parameter_property $emac1_pin_mux_param_name allowed_ranges] + + set emac0_ptp_enabled [expr {[string compare $emac0_pin_mux_value [FPGA_MUX_VALUE]] == 0 && [lsearch $emac0_pin_mux_allowed_ranges [FPGA_MUX_VALUE]] != -1}] + set emac1_ptp_enabled [expr {[string compare $emac1_pin_mux_value [FPGA_MUX_VALUE]] == 0 && [lsearch $emac1_pin_mux_allowed_ranges [FPGA_MUX_VALUE]] != -1}] + + set emac0_io_enabled [expr {[string compare $emac0_pin_mux_value "HPS I/O Set 0"] == 0 && [lsearch $emac0_pin_mux_allowed_ranges "HPS I/O Set 0"] != -1}] + set emac1_io_enabled [expr {[string compare $emac1_pin_mux_value "HPS I/O Set 0"] == 0 && [lsearch $emac1_pin_mux_allowed_ranges "HPS I/O Set 0"] != -1}] + + set emac0_ptp [get_parameter_value EMAC0_PTP] + set emac1_ptp [get_parameter_value EMAC1_PTP] + + if {$emac0_ptp && $emac0_io_enabled} { + set emac0_ptp_enabled 1 + } + if {$emac1_ptp && $emac1_io_enabled} { + set emac1_ptp_enabled 1 + } + + if {$emac0_ptp_enabled || $emac1_ptp_enabled } { + set instance_name clocks_resets + fpga_interfaces::add_interface emac_ptp_ref_clock clock Input + fpga_interfaces::add_interface_port emac_ptp_ref_clock emac_ptp_ref_clk clk Input 1 $instance_name ptp_ref_clk + } + + # TODO: elab peripherals that mux signals to the fpga + elab_FPGA_Peripheral_Signals $device_family + + set_parameter_value DEVICE_FAMILY [get_parameter_value SYS_INFO_DEVICE_FAMILY] +} + +proc elab_MPU_EVENTS {device_family} { + if [is_enabled MPU_EVENTS_Enable] { + set instance_name mpu_events + set atom_name hps_interface_mpu_event_standby + set location [locations::get_fpga_location $instance_name $atom_name] + + set iface_name "h2f_mpu_events" + set z "h2f_mpu_" + fpga_interfaces::add_interface $iface_name conduit Input + fpga_interfaces::add_interface_port $iface_name ${z}eventi eventi Input 1 $instance_name eventi + fpga_interfaces::add_interface_port $iface_name ${z}evento evento Output 1 $instance_name evento + fpga_interfaces::add_interface_port $iface_name ${z}standbywfe standbywfe Output 2 $instance_name standbywfe + fpga_interfaces::add_interface_port $iface_name ${z}standbywfi standbywfi Output 2 $instance_name standbywfi + + set wys_atom_name [generic_atom_to_wys_atom $device_family $atom_name] + fpga_interfaces::add_module_instance $instance_name $wys_atom_name $location + } +} + +proc elab_DEBUGAPB {device_family} { + set instance_name debug_apb + set atom_name hps_interface_dbg_apb + set location [locations::get_fpga_location $instance_name $atom_name] + set wys_atom_name [generic_atom_to_wys_atom $device_family $atom_name] + fpga_interfaces::add_module_instance $instance_name $wys_atom_name $location + + if [is_enabled DEBUGAPB_Enable] { + set clock_name "h2f_debug_apb_clock" + fpga_interfaces::add_interface $clock_name clock Input + fpga_interfaces::add_interface_port $clock_name "h2f_dbg_apb_clk" clk Input 1 $instance_name P_CLK + + set reset_name "h2f_debug_apb_reset" + fpga_interfaces::add_interface $reset_name reset Output + fpga_interfaces::add_interface_port $reset_name "h2f_dbg_apb_rst_n" reset_n Output 1 $instance_name P_RESET_N + fpga_interfaces::set_interface_property $reset_name associatedClock $clock_name + + set iface_name "h2f_debug_apb" + set z "h2f_dbg_apb_" + fpga_interfaces::add_interface $iface_name apb master + fpga_interfaces::add_interface_port $iface_name "${z}PADDR" paddr Output 18 $instance_name P_ADDR + fpga_interfaces::add_interface_port $iface_name "${z}PADDR31" paddr31 Output 1 $instance_name P_ADDR_31 + fpga_interfaces::add_interface_port $iface_name "${z}PENABLE" penable Output 1 $instance_name P_ENABLE + fpga_interfaces::add_interface_port $iface_name "${z}PRDATA" prdata Input 32 $instance_name P_RDATA + fpga_interfaces::add_interface_port $iface_name "${z}PREADY" pready Input 1 $instance_name P_READY + fpga_interfaces::add_interface_port $iface_name "${z}PSEL" psel Output 1 $instance_name P_SEL + fpga_interfaces::add_interface_port $iface_name "${z}PSLVERR" pslverr Input 1 $instance_name P_SLV_ERR + fpga_interfaces::add_interface_port $iface_name "${z}PWDATA" pwdata Output 32 $instance_name P_WDATA + fpga_interfaces::add_interface_port $iface_name "${z}PWRITE" pwrite Output 1 $instance_name P_WRITE + fpga_interfaces::set_interface_property $iface_name associatedClock $clock_name + fpga_interfaces::set_interface_property $iface_name associatedReset $reset_name + + set iface_name "h2f_debug_apb_sideband" + set z "h2f_dbg_apb_" + fpga_interfaces::add_interface $iface_name conduit Input + fpga_interfaces::add_interface_port $iface_name "${z}PCLKEN" pclken Input 1 $instance_name P_CLK_EN + fpga_interfaces::add_interface_port $iface_name "${z}DBG_APB_DISABLE" dbg_apb_disable Input 1 $instance_name DBG_APB_DISABLE + fpga_interfaces::set_interface_property $iface_name associatedClock $clock_name + fpga_interfaces::set_interface_property $iface_name associatedReset $reset_name + + } else { + # Tie low when FPGA debug apb not being used + fpga_interfaces::set_instance_port_termination ${instance_name} "P_CLK_EN" 1 0 0:0 0 + fpga_interfaces::set_instance_port_termination ${instance_name} "DBG_APB_DISABLE" 1 0 0:0 0 + } +} + +proc elab_STM {device_family} { + if [is_enabled STM_Enable] { + set instance_name stm_event + set atom_name hps_interface_stm_event + set location [locations::get_fpga_location $instance_name $atom_name] + + fpga_interfaces::add_interface f2h_stm_hw_events conduit Input + fpga_interfaces::add_interface_port f2h_stm_hw_events f2h_stm_hwevents stm_hwevents Input 28 $instance_name stm_event + + set wys_atom_name [generic_atom_to_wys_atom $device_family $atom_name] + fpga_interfaces::add_module_instance $instance_name $wys_atom_name $location + } +} + +proc elab_CTI {device_family} { + set instance_name cross_trigger_interface + set atom_name hps_interface_cross_trigger + set location [locations::get_fpga_location $instance_name $atom_name] + + if [is_enabled CTI_Enable] { + set iface_name "h2f_cti" + set z "h2f_cti_" + fpga_interfaces::add_interface $iface_name conduit Input + fpga_interfaces::add_interface_port $iface_name ${z}trig_in trig_in Input 8 $instance_name trig_in + fpga_interfaces::add_interface_port $iface_name ${z}trig_in_ack trig_in_ack Output 8 $instance_name trig_inack + fpga_interfaces::add_interface_port $iface_name ${z}trig_out trig_out Output 8 $instance_name trig_out + fpga_interfaces::add_interface_port $iface_name ${z}trig_out_ack trig_out_ack Input 8 $instance_name trig_outack + # case:105603 hide asicctl output signal + # fpga_interfaces::add_interface_port $iface_name ${z}asicctl asicctl Output 8 $instance_name asicctl + fpga_interfaces::add_interface_port $iface_name ${z}fpga_clk_en fpga_clk_en Input 1 $instance_name clk_en + fpga_interfaces::set_interface_property $iface_name associatedClock h2f_cti_clock + fpga_interfaces::set_interface_property $iface_name associatedReset h2f_reset + + fpga_interfaces::add_interface h2f_cti_clock clock Input + fpga_interfaces::add_interface_port h2f_cti_clock h2f_cti_clk clk Input 1 $instance_name clk + + set wys_atom_name [generic_atom_to_wys_atom $device_family $atom_name] + fpga_interfaces::add_module_instance $instance_name $wys_atom_name $location + } +} + +proc elab_TPIUFPGA {device_family} { + set instance_name tpiu + set atom_name hps_interface_tpiu_trace + set location [locations::get_fpga_location $instance_name $atom_name] + + set wys_atom_name [generic_atom_to_wys_atom $device_family $atom_name] + fpga_interfaces::add_module_instance $instance_name $wys_atom_name $location + + if { [string compare [get_parameter_value TPIUFPGA_Enable] "true" ] == 0 } { + set_parameter_property TPIUFPGA_alt enabled true + set iface_name "h2f_tpiu" + set z "h2f_tpiu_" + fpga_interfaces::add_interface $iface_name conduit input + fpga_interfaces::add_interface_port $iface_name ${z}clk_ctl clk_ctl Input 1 $instance_name traceclk_ctl + fpga_interfaces::add_interface_port $iface_name ${z}data data Output 32 $instance_name trace_data + + # case 245159 + if {[string compare [get_parameter_value TPIUFPGA_alt] "true" ] == 0} { + fpga_interfaces::add_interface_port $iface_name ${z}clkin clkin Input 1 $instance_name traceclkin + } else { + set iface_name "h2f_tpiu_clock_in" + fpga_interfaces::add_interface $iface_name clock input + fpga_interfaces::add_interface_port $iface_name ${z}clk_in clk Input 1 $instance_name traceclkin + } + + set clock_in_rate [get_parameter_value H2F_TPIU_CLOCK_IN_FREQ] + set clock_rate [expr {$clock_in_rate / 2}] + set iface_name "h2f_tpiu_clock" + fpga_interfaces::add_interface $iface_name clock output + fpga_interfaces::add_interface_port $iface_name ${z}clk clk Output 1 $instance_name traceclk + fpga_interfaces::set_interface_property $iface_name clockRateKnown true + fpga_interfaces::set_interface_property $iface_name clockRate $clock_rate + + add_clock_constraint_if_valid $clock_rate "*|fpga_interfaces|${instance_name}|traceclk" + + } else { + set_parameter_property TPIUFPGA_alt enabled false + fpga_interfaces::set_instance_port_termination ${instance_name} "traceclk_ctl" 1 1 0:0 1 + } +} + +proc elab_GP {device_family} { + if [is_enabled GP_Enable] { + set instance_name h2f_gp + set atom_name hps_interface_mpu_general_purpose + set location [locations::get_fpga_location $instance_name $atom_name] + + set iface_name "h2f_gp" + set z "h2f_gp_" + fpga_interfaces::add_interface $iface_name conduit Input + fpga_interfaces::add_interface_port $iface_name ${z}in gp_in Input 32 $instance_name gp_in + fpga_interfaces::add_interface_port $iface_name ${z}out gp_out Output 32 $instance_name gp_out + + set wys_atom_name [generic_atom_to_wys_atom $device_family $atom_name] + fpga_interfaces::add_module_instance $instance_name $wys_atom_name $location + } +} + +proc elab_BOOTFROMFPGA {device_family} { + set instance_name boot_from_fpga + set atom_name hps_interface_boot_from_fpga + set location [locations::get_fpga_location $instance_name $atom_name] + set wys_atom_name [generic_atom_to_wys_atom $device_family $atom_name] + fpga_interfaces::add_module_instance $instance_name $wys_atom_name $location + + set bsel_en [expr { [string compare [get_parameter_value BSEL_EN] "true" ] == 0 } ] + set bsel [get_parameter_value BSEL] + set csel_en [expr { [string compare [get_parameter_value CSEL_EN] "true" ] == 0 } ] + set csel [get_parameter_value CSEL] + set boot_from_fpga_enable [expr { [string compare [get_parameter_value BOOTFROMFPGA_Enable] "true" ] == 0 } ] + set ini_string [get_parameter_value quartus_ini_hps_ip_enable_bsel_csel] + set ini_enabled [expr { [string compare $ini_string "true" ] == 0 } ] + + # force disable bsel/csel by default + if {!$ini_enabled} { + set bsel_en 0 + set bsel 1 + set csel_en 0 + set csel 1 + } + + # when INI enabled, the controls should appear in the GUI + foreach parameter {BSEL BSEL_EN CSEL CSEL_EN} { + set_parameter_property $parameter visible $ini_string + set_parameter_property $parameter enabled $ini_string + } + + fpga_interfaces::set_instance_port_termination ${instance_name} "bsel" 3 0 2:0 $bsel + fpga_interfaces::set_instance_port_termination ${instance_name} "csel" 2 0 1:0 $csel + + if {$bsel_en} { + fpga_interfaces::set_instance_port_termination ${instance_name} "bsel_en" 1 0 0:0 1 + } else { + fpga_interfaces::set_instance_port_termination ${instance_name} "bsel_en" 1 0 0:0 0 + } + + if {$csel_en} { + fpga_interfaces::set_instance_port_termination ${instance_name} "csel_en" 1 0 0:0 1 + } else { + fpga_interfaces::set_instance_port_termination ${instance_name} "csel_en" 1 0 0:0 0 + } + + if {$boot_from_fpga_enable} { + set iface_name "f2h_boot_from_fpga" + set z "f2h_boot_from_fpga_" + fpga_interfaces::add_interface $iface_name conduit Input + fpga_interfaces::add_interface_port $iface_name "${z}ready" boot_from_fpga_ready Input 1 $instance_name boot_from_fpga_ready + fpga_interfaces::add_interface_port $iface_name "${z}on_failure" boot_from_fpga_on_failure Input 1 $instance_name boot_from_fpga_on_failure + } else { + fpga_interfaces::set_instance_port_termination ${instance_name} "boot_from_fpga_ready" 1 0 0:0 0 + fpga_interfaces::set_instance_port_termination ${instance_name} "boot_from_fpga_on_failure" 1 0 0:0 0 + } + + if {$boot_from_fpga_enable} { + send_message info "Ensure that valid Cortex A9 boot code is available to the HPS system when enabling boot from FPGA and h2f_axi_master interface is connecting to slave component start at address 0x0." + } + + if {$bsel_en && $bsel == 1 && !$boot_from_fpga_enable} { + send_message warning "Boot from FPGA ready must be enabled to correctly boot from the FPGA." + } +} + + +proc elab_F2S {device_family} { + set instance_name fpga2hps + set atom_name hps_interface_fpga2hps + set location [locations::get_fpga_location $instance_name $atom_name] + set termination_value 3 + + set wys_atom_name [generic_atom_to_wys_atom $device_family $atom_name] + fpga_interfaces::add_module_instance $instance_name $wys_atom_name $location + + set addr_width 32 + set width [get_parameter_value F2S_Width] + if {$width > 0} { + set data_width 32 + set strb_width 4 + set termination_value 0 + if {$width == 2} { + set data_width 64 + set strb_width 8 + set termination_value 1 + } elseif {$width == 3} { + set data_width 128 + set strb_width 16 + set termination_value 2 + } + + set clock_name "f2h_axi_clock" + fpga_interfaces::add_interface $clock_name clock Input + fpga_interfaces::add_interface_port $clock_name f2h_axi_clk clk Input 1 $instance_name clk + + set iface_name "f2h_axi_slave" + set z "f2h_" + + fpga_interfaces::add_interface $iface_name axi slave + fpga_interfaces::set_interface_property $iface_name associatedClock $clock_name + fpga_interfaces::set_interface_property $iface_name associatedReset h2f_reset + fpga_interfaces::set_interface_property $iface_name readAcceptanceCapability 8 + fpga_interfaces::set_interface_property $iface_name writeAcceptanceCapability 8 + fpga_interfaces::set_interface_property $iface_name combinedAcceptanceCapability 16 + fpga_interfaces::set_interface_property $iface_name readDataReorderingDepth 16 + fpga_interfaces::set_interface_meta_property $iface_name data_width $data_width + fpga_interfaces::set_interface_meta_property $iface_name address_width $addr_width + + fpga_interfaces::add_interface_port $iface_name ${z}AWID awid Input 8 $instance_name awid + fpga_interfaces::add_interface_port $iface_name ${z}AWADDR awaddr Input $addr_width $instance_name awaddr + fpga_interfaces::add_interface_port $iface_name ${z}AWLEN awlen Input 4 $instance_name awlen + fpga_interfaces::add_interface_port $iface_name ${z}AWSIZE awsize Input 3 $instance_name awsize + fpga_interfaces::add_interface_port $iface_name ${z}AWBURST awburst Input 2 $instance_name awburst + fpga_interfaces::add_interface_port $iface_name ${z}AWLOCK awlock Input 2 $instance_name awlock + fpga_interfaces::add_interface_port $iface_name ${z}AWCACHE awcache Input 4 $instance_name awcache + fpga_interfaces::add_interface_port $iface_name ${z}AWPROT awprot Input 3 $instance_name awprot + fpga_interfaces::add_interface_port $iface_name ${z}AWVALID awvalid Input 1 $instance_name awvalid + fpga_interfaces::add_interface_port $iface_name ${z}AWREADY awready Output 1 $instance_name awready + fpga_interfaces::add_interface_port $iface_name ${z}AWUSER awuser Input 5 $instance_name awuser + + fpga_interfaces::add_interface_port $iface_name ${z}WID wid Input 8 $instance_name wid + fpga_interfaces::add_interface_port $iface_name ${z}WDATA wdata Input $data_width $instance_name wdata + fpga_interfaces::add_interface_port $iface_name ${z}WSTRB wstrb Input $strb_width $instance_name wstrb + fpga_interfaces::add_interface_port $iface_name ${z}WLAST wlast Input 1 $instance_name wlast + fpga_interfaces::add_interface_port $iface_name ${z}WVALID wvalid Input 1 $instance_name wvalid + fpga_interfaces::add_interface_port $iface_name ${z}WREADY wready Output 1 $instance_name wready + + fpga_interfaces::add_interface_port $iface_name ${z}BID bid Output 8 $instance_name bid + fpga_interfaces::add_interface_port $iface_name ${z}BRESP bresp Output 2 $instance_name bresp + fpga_interfaces::add_interface_port $iface_name ${z}BVALID bvalid Output 1 $instance_name bvalid + fpga_interfaces::add_interface_port $iface_name ${z}BREADY bready Input 1 $instance_name bready + + + fpga_interfaces::add_interface_port $iface_name ${z}ARID arid Input 8 $instance_name arid + fpga_interfaces::add_interface_port $iface_name ${z}ARADDR araddr Input $addr_width $instance_name araddr + fpga_interfaces::add_interface_port $iface_name ${z}ARLEN arlen Input 4 $instance_name arlen + fpga_interfaces::add_interface_port $iface_name ${z}ARSIZE arsize Input 3 $instance_name arsize + fpga_interfaces::add_interface_port $iface_name ${z}ARBURST arburst Input 2 $instance_name arburst + fpga_interfaces::add_interface_port $iface_name ${z}ARLOCK arlock Input 2 $instance_name arlock + fpga_interfaces::add_interface_port $iface_name ${z}ARCACHE arcache Input 4 $instance_name arcache + fpga_interfaces::add_interface_port $iface_name ${z}ARPROT arprot Input 3 $instance_name arprot + fpga_interfaces::add_interface_port $iface_name ${z}ARVALID arvalid Input 1 $instance_name arvalid + fpga_interfaces::add_interface_port $iface_name ${z}ARREADY arready Output 1 $instance_name arready + fpga_interfaces::add_interface_port $iface_name ${z}ARUSER aruser Input 5 $instance_name aruser + + fpga_interfaces::add_interface_port $iface_name ${z}RID rid Output 8 $instance_name rid + fpga_interfaces::add_interface_port $iface_name ${z}RDATA rdata Output $data_width $instance_name rdata + fpga_interfaces::add_interface_port $iface_name ${z}RRESP rresp Output 2 $instance_name rresp + fpga_interfaces::add_interface_port $iface_name ${z}RLAST rlast Output 1 $instance_name rlast + fpga_interfaces::add_interface_port $iface_name ${z}RVALID rvalid Output 1 $instance_name rvalid + fpga_interfaces::add_interface_port $iface_name ${z}RREADY rready Input 1 $instance_name rready + } + fpga_interfaces::set_instance_port_termination ${instance_name} "port_size_config" 2 0 1:0 $termination_value +} + +proc elab_S2F {device_family} { + set instance_name hps2fpga + set atom_name hps_interface_hps2fpga + set location [locations::get_fpga_location $instance_name $atom_name] + set termination_value 3 + + set wys_atom_name [generic_atom_to_wys_atom $device_family $atom_name] + fpga_interfaces::add_module_instance $instance_name $wys_atom_name $location + + set addr_width 30 + set id_width 12 + set width [get_parameter_value S2F_Width] + if {$width > 0} { + set data_width 32 + set strb_width 4 + set termination_value 0 + + if {$width == 2} { + set data_width 64 + set strb_width 8 + set termination_value 1 + + } elseif {$width == 3} { + set data_width 128 + set strb_width 16 + set termination_value 2 + } + + set clock_name "h2f_axi_clock" + fpga_interfaces::add_interface $clock_name clock Input + fpga_interfaces::add_interface_port $clock_name h2f_axi_clk clk Input 1 $instance_name clk + + set iface_name "h2f_axi_master" + set z "h2f_" + + fpga_interfaces::add_interface $iface_name axi master + fpga_interfaces::set_interface_property $iface_name associatedClock $clock_name + fpga_interfaces::set_interface_property $iface_name associatedReset h2f_reset + fpga_interfaces::set_interface_property $iface_name readIssuingCapability 8 + fpga_interfaces::set_interface_property $iface_name writeIssuingCapability 8 + fpga_interfaces::set_interface_property $iface_name combinedIssuingCapability 16 + +# set svd_path [file join $::env(QUARTUS_ROOTDIR) .. ip altera hps altera_hps golden_ref_design_CMSIS_1_1_to_arm_v2.svd] +# send_message info "REMOVE! SVD_PATH = $svd_path" +# fpga_interfaces::set_interface_property $iface_name CMSIS_SVD_FILE $svd_path +# fpga_interfaces::set_interface_property $iface_name SVD_ADDRESS_GROUP hps +# fpga_interfaces::set_interface_property $iface_name SVD_ADDRESS_OFFSET [expr {0xC0000000}] + fpga_interfaces::set_interface_meta_property $iface_name data_width $data_width + fpga_interfaces::set_interface_meta_property $iface_name address_width $addr_width + fpga_interfaces::set_interface_meta_property $iface_name id_width $id_width + + fpga_interfaces::add_interface_port $iface_name ${z}AWID awid Output $id_width $instance_name awid + fpga_interfaces::add_interface_port $iface_name ${z}AWADDR awaddr Output $addr_width $instance_name awaddr + fpga_interfaces::add_interface_port $iface_name ${z}AWLEN awlen Output 4 $instance_name awlen + fpga_interfaces::add_interface_port $iface_name ${z}AWSIZE awsize Output 3 $instance_name awsize + fpga_interfaces::add_interface_port $iface_name ${z}AWBURST awburst Output 2 $instance_name awburst + fpga_interfaces::add_interface_port $iface_name ${z}AWLOCK awlock Output 2 $instance_name awlock + fpga_interfaces::add_interface_port $iface_name ${z}AWCACHE awcache Output 4 $instance_name awcache + fpga_interfaces::add_interface_port $iface_name ${z}AWPROT awprot Output 3 $instance_name awprot + fpga_interfaces::add_interface_port $iface_name ${z}AWVALID awvalid Output 1 $instance_name awvalid + fpga_interfaces::add_interface_port $iface_name ${z}AWREADY awready Input 1 $instance_name awready + + fpga_interfaces::add_interface_port $iface_name ${z}WID wid Output $id_width $instance_name wid + fpga_interfaces::add_interface_port $iface_name ${z}WDATA wdata Output $data_width $instance_name wdata + fpga_interfaces::add_interface_port $iface_name ${z}WSTRB wstrb Output $strb_width $instance_name wstrb + fpga_interfaces::add_interface_port $iface_name ${z}WLAST wlast Output 1 $instance_name wlast + fpga_interfaces::add_interface_port $iface_name ${z}WVALID wvalid Output 1 $instance_name wvalid + fpga_interfaces::add_interface_port $iface_name ${z}WREADY wready Input 1 $instance_name wready + + fpga_interfaces::add_interface_port $iface_name ${z}BID bid Input $id_width $instance_name bid + fpga_interfaces::add_interface_port $iface_name ${z}BRESP bresp Input 2 $instance_name bresp + fpga_interfaces::add_interface_port $iface_name ${z}BVALID bvalid Input 1 $instance_name bvalid + fpga_interfaces::add_interface_port $iface_name ${z}BREADY bready Output 1 $instance_name bready + + fpga_interfaces::add_interface_port $iface_name ${z}ARID arid Output $id_width $instance_name arid + fpga_interfaces::add_interface_port $iface_name ${z}ARADDR araddr Output $addr_width $instance_name araddr + fpga_interfaces::add_interface_port $iface_name ${z}ARLEN arlen Output 4 $instance_name arlen + fpga_interfaces::add_interface_port $iface_name ${z}ARSIZE arsize Output 3 $instance_name arsize + fpga_interfaces::add_interface_port $iface_name ${z}ARBURST arburst Output 2 $instance_name arburst + fpga_interfaces::add_interface_port $iface_name ${z}ARLOCK arlock Output 2 $instance_name arlock + fpga_interfaces::add_interface_port $iface_name ${z}ARCACHE arcache Output 4 $instance_name arcache + fpga_interfaces::add_interface_port $iface_name ${z}ARPROT arprot Output 3 $instance_name arprot + fpga_interfaces::add_interface_port $iface_name ${z}ARVALID arvalid Output 1 $instance_name arvalid + fpga_interfaces::add_interface_port $iface_name ${z}ARREADY arready Input 1 $instance_name arready + + fpga_interfaces::add_interface_port $iface_name ${z}RID rid Input $id_width $instance_name rid + fpga_interfaces::add_interface_port $iface_name ${z}RDATA rdata Input $data_width $instance_name rdata + fpga_interfaces::add_interface_port $iface_name ${z}RRESP rresp Input 2 $instance_name rresp + fpga_interfaces::add_interface_port $iface_name ${z}RLAST rlast Input 1 $instance_name rlast + fpga_interfaces::add_interface_port $iface_name ${z}RVALID rvalid Input 1 $instance_name rvalid + fpga_interfaces::add_interface_port $iface_name ${z}RREADY rready Output 1 $instance_name rready + + } + fpga_interfaces::set_instance_port_termination ${instance_name} "port_size_config" 2 0 1:0 $termination_value +} + +proc elab_LWH2F {device_family} { + set instance_name hps2fpga_light_weight + set atom_name hps_interface_hps2fpga_light_weight + set location [locations::get_fpga_location $instance_name $atom_name] + + if [is_enabled LWH2F_Enable] { + set addr_width 21 + set data_width 32 + set strb_width 4 + set id_width 12 + set clock_name "h2f_lw_axi_clock" + fpga_interfaces::add_interface $clock_name clock Input + fpga_interfaces::add_interface_port $clock_name h2f_lw_axi_clk clk Input 1 $instance_name clk + + set iface_name "h2f_lw_axi_master" + set z "h2f_lw_" + fpga_interfaces::add_interface $iface_name axi master +# fpga_interfaces::set_interface_property $iface_name SVD_ADDRESS_GROUP hps +# fpga_interfaces::set_interface_property $iface_name SVD_ADDRESS_OFFSET [expr {0xFC000000}] + fpga_interfaces::set_interface_property $iface_name associatedClock $clock_name + fpga_interfaces::set_interface_property $iface_name associatedReset h2f_reset + fpga_interfaces::set_interface_property $iface_name readIssuingCapability 8 + fpga_interfaces::set_interface_property $iface_name writeIssuingCapability 8 + fpga_interfaces::set_interface_property $iface_name combinedIssuingCapability 16 + fpga_interfaces::set_interface_meta_property $iface_name data_width $data_width + fpga_interfaces::set_interface_meta_property $iface_name address_width $addr_width + fpga_interfaces::set_interface_meta_property $iface_name id_width $id_width + + fpga_interfaces::add_interface_port $iface_name ${z}AWID awid Output $id_width $instance_name awid + fpga_interfaces::add_interface_port $iface_name ${z}AWADDR awaddr Output $addr_width $instance_name awaddr + fpga_interfaces::add_interface_port $iface_name ${z}AWLEN awlen Output 4 $instance_name awlen + fpga_interfaces::add_interface_port $iface_name ${z}AWSIZE awsize Output 3 $instance_name awsize + fpga_interfaces::add_interface_port $iface_name ${z}AWBURST awburst Output 2 $instance_name awburst + fpga_interfaces::add_interface_port $iface_name ${z}AWLOCK awlock Output 2 $instance_name awlock + fpga_interfaces::add_interface_port $iface_name ${z}AWCACHE awcache Output 4 $instance_name awcache + fpga_interfaces::add_interface_port $iface_name ${z}AWPROT awprot Output 3 $instance_name awprot + fpga_interfaces::add_interface_port $iface_name ${z}AWVALID awvalid Output 1 $instance_name awvalid + fpga_interfaces::add_interface_port $iface_name ${z}AWREADY awready Input 1 $instance_name awready + + fpga_interfaces::add_interface_port $iface_name ${z}WID wid Output $id_width $instance_name wid + fpga_interfaces::add_interface_port $iface_name ${z}WDATA wdata Output $data_width $instance_name wdata + fpga_interfaces::add_interface_port $iface_name ${z}WSTRB wstrb Output $strb_width $instance_name wstrb + fpga_interfaces::add_interface_port $iface_name ${z}WLAST wlast Output 1 $instance_name wlast + fpga_interfaces::add_interface_port $iface_name ${z}WVALID wvalid Output 1 $instance_name wvalid + fpga_interfaces::add_interface_port $iface_name ${z}WREADY wready Input 1 $instance_name wready + + fpga_interfaces::add_interface_port $iface_name ${z}BID bid Input $id_width $instance_name bid + fpga_interfaces::add_interface_port $iface_name ${z}BRESP bresp Input 2 $instance_name bresp + fpga_interfaces::add_interface_port $iface_name ${z}BVALID bvalid Input 1 $instance_name bvalid + fpga_interfaces::add_interface_port $iface_name ${z}BREADY bready Output 1 $instance_name bready + + fpga_interfaces::add_interface_port $iface_name ${z}ARID arid Output $id_width $instance_name arid + fpga_interfaces::add_interface_port $iface_name ${z}ARADDR araddr Output $addr_width $instance_name araddr + fpga_interfaces::add_interface_port $iface_name ${z}ARLEN arlen Output 4 $instance_name arlen + fpga_interfaces::add_interface_port $iface_name ${z}ARSIZE arsize Output 3 $instance_name arsize + fpga_interfaces::add_interface_port $iface_name ${z}ARBURST arburst Output 2 $instance_name arburst + fpga_interfaces::add_interface_port $iface_name ${z}ARLOCK arlock Output 2 $instance_name arlock + fpga_interfaces::add_interface_port $iface_name ${z}ARCACHE arcache Output 4 $instance_name arcache + fpga_interfaces::add_interface_port $iface_name ${z}ARPROT arprot Output 3 $instance_name arprot + fpga_interfaces::add_interface_port $iface_name ${z}ARVALID arvalid Output 1 $instance_name arvalid + fpga_interfaces::add_interface_port $iface_name ${z}ARREADY arready Input 1 $instance_name arready + + fpga_interfaces::add_interface_port $iface_name ${z}RID rid Input $id_width $instance_name rid + fpga_interfaces::add_interface_port $iface_name ${z}RDATA rdata Input $data_width $instance_name rdata + fpga_interfaces::add_interface_port $iface_name ${z}RRESP rresp Input 2 $instance_name rresp + fpga_interfaces::add_interface_port $iface_name ${z}RLAST rlast Input 1 $instance_name rlast + fpga_interfaces::add_interface_port $iface_name ${z}RVALID rvalid Input 1 $instance_name rvalid + fpga_interfaces::add_interface_port $iface_name ${z}RREADY rready Output 1 $instance_name rready + + set wys_atom_name [generic_atom_to_wys_atom $device_family $atom_name] + fpga_interfaces::add_module_instance $instance_name $wys_atom_name $location + } +} + +proc elab_F2SDRAM {device_family} { + f2sdram::init_registers + + set instance_name f2sdram + set atom_name hps_interface_fpga2sdram + set location [locations::get_fpga_location $instance_name $atom_name] + set wys_atom_name [generic_atom_to_wys_atom $device_family $atom_name] + + fpga_interfaces::add_module_instance $instance_name $wys_atom_name $location + + set use_fast_sim_model [expr { [string compare [get_parameter_value quartus_ini_hps_ip_fast_f2sdram_sim_model] "true" ] == 0 }] + set bonding_out_signal [expr { [string compare [get_parameter_value BONDING_OUT_ENABLED] "true"] == 0} && {[string compare [get_parameter_value quartus_ini_hps_ip_f2sdram_bonding_out] "true"] == 0}] + #newly added + set width_list [get_parameter_value F2SDRAM_Width] + set rows [llength $width_list] + if {$rows > 0} { + # TODO: move outside of 'if' once registers are rendered + + + set type_list [get_parameter_value F2SDRAM_Type] + for {set i 0} {${i} < $rows} {incr i} { + set width [lindex $width_list $i] + set type_choice [lindex $type_list $i] + + set type "axi" + set type_id 0 + if { [string compare $type_choice [F2HSDRAM_AVM]] == 0 } { + set type "avalon" + set type_id 1 + } elseif { [string compare $type_choice [F2HSDRAM_AVM_WRITEONLY]] == 0 } { + set type "avalon" + set type_id 2 + } elseif { [string compare $type_choice [F2HSDRAM_AVM_READONLY]] == 0 } { + set type "avalon" + set type_id 3 + } + + set sim_is_synth [expr !$use_fast_sim_model] + + # To make sure bonding_out_signal only being added once even thought there are more than one f2sdram + if {$i == 0 } { + set bonding_out_signal [expr { [string compare [get_parameter_value BONDING_OUT_ENABLED] "true"] == 0} && {[string compare [get_parameter_value quartus_ini_hps_ip_f2sdram_bonding_out] "true"] == 0}] + } else { + set bonding_out_signal 0 + } + + f2sdram::add_port registers $i $type_id $width $instance_name $sim_is_synth $bonding_out_signal + } + f2sdram::add_sdc $use_fast_sim_model + fpga_interfaces::set_property IMPLEMENT_F2SDRAM_MEMORY_BACKED_SIM $use_fast_sim_model + + } + # write the registers out + f2sdram::render_registers registers $instance_name +} + +proc elab_clocks_resets {device_family} { + set instance_name clocks_resets + set atom_name hps_interface_clocks_resets + set location [locations::get_fpga_location $instance_name $atom_name] + + set wys_atom_name [generic_atom_to_wys_atom $device_family $atom_name] + fpga_interfaces::add_module_instance $instance_name $wys_atom_name $location + + fpga_interfaces::add_interface h2f_reset reset Output + fpga_interfaces::add_interface_port h2f_reset h2f_rst_n reset_n Output 1 $instance_name + fpga_interfaces::set_interface_property h2f_reset synchronousEdges none + fpga_interfaces::set_interface_property h2f_reset associatedResetSinks none + + if [is_enabled S2FCLK_COLDRST_Enable] { + fpga_interfaces::add_interface h2f_cold_reset reset Output + fpga_interfaces::add_interface_port h2f_cold_reset h2f_cold_rst_n reset_n Output 1 $instance_name + fpga_interfaces::set_interface_property h2f_cold_reset synchronousEdges none + fpga_interfaces::set_interface_property h2f_cold_reset associatedResetSinks none + } + + if [is_enabled F2SCLK_COLDRST_Enable] { + fpga_interfaces::add_interface f2h_cold_reset_req reset Input + fpga_interfaces::add_interface_port f2h_cold_reset_req f2h_cold_rst_req_n reset_n Input 1 $instance_name + fpga_interfaces::set_interface_property f2h_cold_reset_req synchronousEdges none + fpga_interfaces::set_interface_property h2f_reset associatedResetSinks f2h_cold_reset_req + if [is_enabled S2FCLK_COLDRST_Enable] { + fpga_interfaces::set_interface_property h2f_cold_reset associatedResetSinks f2h_cold_reset_req + } + } else { + fpga_interfaces::set_instance_port_termination ${instance_name} "f2h_cold_rst_req_n" 1 1 0:0 1 + } + + if [is_enabled S2FCLK_PENDINGRST_Enable] { + fpga_interfaces::add_interface h2f_warm_reset_handshake conduit Output + fpga_interfaces::add_interface_port h2f_warm_reset_handshake h2f_pending_rst_req_n h2f_pending_rst_req_n Output 1 $instance_name + fpga_interfaces::add_interface_port h2f_warm_reset_handshake f2h_pending_rst_ack_n f2h_pending_rst_ack_n Input 1 $instance_name f2h_pending_rst_ack + } else { + fpga_interfaces::set_instance_port_termination ${instance_name} "f2h_pending_rst_ack" 1 1 0:0 1 + } + + if [is_enabled F2SCLK_DBGRST_Enable] { + fpga_interfaces::add_interface f2h_debug_reset_req reset Input + fpga_interfaces::add_interface_port f2h_debug_reset_req f2h_dbg_rst_req_n reset_n Input 1 $instance_name + fpga_interfaces::set_interface_property f2h_debug_reset_req synchronousEdges none + } else { + fpga_interfaces::set_instance_port_termination ${instance_name} "f2h_dbg_rst_req_n" 1 1 0:0 1 + } + + if [is_enabled F2SCLK_WARMRST_Enable] { + fpga_interfaces::add_interface f2h_warm_reset_req reset Input + fpga_interfaces::add_interface_port f2h_warm_reset_req f2h_warm_rst_req_n reset_n Input 1 $instance_name + fpga_interfaces::set_interface_property f2h_warm_reset_req synchronousEdges none + + if [is_enabled F2SCLK_COLDRST_Enable] { + fpga_interfaces::set_interface_property h2f_reset associatedResetSinks {f2h_warm_reset_req f2h_cold_reset_req} + } else { + fpga_interfaces::set_interface_property h2f_reset associatedResetSinks {f2h_warm_reset_req} + } + } else { + fpga_interfaces::set_instance_port_termination ${instance_name} "f2h_warm_rst_req_n" 1 1 0:0 1 + } + + if [is_enabled S2FCLK_USER0CLK_Enable] { + fpga_interfaces::add_interface h2f_user0_clock clock Output + fpga_interfaces::add_interface_port h2f_user0_clock h2f_user0_clk clk Output 1 $instance_name + set frequency [get_parameter_value S2FCLK_USER0CLK_FREQ] + set frequency [expr {$frequency * [MHZ_TO_HZ]}] + fpga_interfaces::set_interface_property h2f_user0_clock clockRateKnown true + fpga_interfaces::set_interface_property h2f_user0_clock clockRate $frequency + add_clock_constraint_if_valid $frequency "*|fpga_interfaces|${instance_name}|h2f_user0_clk" + } + + if [is_enabled S2FCLK_USER1CLK_Enable] { + fpga_interfaces::add_interface h2f_user1_clock clock Output + fpga_interfaces::add_interface_port h2f_user1_clock h2f_user1_clk clk Output 1 $instance_name + set frequency [get_parameter_value S2FCLK_USER1CLK_FREQ] + set frequency [expr {$frequency * [MHZ_TO_HZ]}] + fpga_interfaces::set_interface_property h2f_user1_clock clockRateKnown true + fpga_interfaces::set_interface_property h2f_user1_clock clockRate $frequency + add_clock_constraint_if_valid $frequency "*|fpga_interfaces|${instance_name}|h2f_user1_clk" + } + + set_parameter_property S2FCLK_USER2CLK enabled false + + if [is_enabled F2SCLK_PERIPHCLK_Enable] { + fpga_interfaces::add_interface f2h_periph_ref_clock clock Input + fpga_interfaces::add_interface_port f2h_periph_ref_clock f2h_periph_ref_clk clk Input 1 $instance_name + } else { + fpga_interfaces::set_instance_port_termination ${instance_name} "f2h_periph_ref_clk" 1 0 + } + + + if [is_enabled F2SCLK_SDRAMCLK_Enable] { + fpga_interfaces::add_interface f2h_sdram_ref_clock clock Input + fpga_interfaces::add_interface_port f2h_sdram_ref_clock f2h_sdram_ref_clk clk Input 1 $instance_name + } else { + fpga_interfaces::set_instance_port_termination ${instance_name} "f2h_sdram_ref_clk" 1 0 + } +} + +# Elaborate peripheral request interfaces for the fpga and +# the clk/reset per pair +# TODO: Make sure the DMA RTL contains the wrapper +proc elab_DMA {device_family} { + set instance_name dma + set atom_name hps_interface_dma + set location [locations::get_fpga_location $instance_name $atom_name] + + set can_message 0 + set available_list [get_parameter_value DMA_Enable] + if {[llength $available_list] > 0} { + set dma_used 0 + set periph_id 0 + foreach entry $available_list { + if {[string compare $entry "Yes" ] == 0} { + elab_DMA_entry $periph_id $instance_name + set dma_used 1 + if {$periph_id >= 4} { + set can_message 1 + } + } + incr periph_id + } + if $dma_used { + set wys_atom_name [generic_atom_to_wys_atom $device_family $atom_name] + fpga_interfaces::add_module_instance $instance_name $wys_atom_name $location + } + if $can_message { + send_message info "DMA Peripheral Request Interfaces 4-7 may be consumed by an HPS CAN Controller" + } + } +} + +proc elab_DMA_make_conduit_name {periph_id} { + return "f2h_dma_req${periph_id}" +} + +proc elab_DMA_entry {periph_id instance_name} { + set iname [elab_DMA_make_conduit_name $periph_id] + set atom_signal_prefix "channel${periph_id}" + fpga_interfaces::add_interface $iname conduit Output + fpga_interfaces::add_interface_port $iname "${iname}_req" "dma_req" Input 1 $instance_name ${atom_signal_prefix}_req + fpga_interfaces::add_interface_port $iname "${iname}_single" "dma_single" Input 1 $instance_name ${atom_signal_prefix}_single + fpga_interfaces::add_interface_port $iname "${iname}_ack" "dma_ack" Output 1 $instance_name ${atom_signal_prefix}_xx_ack +} + + +proc elab_emac_ptp {device_family} { + # added for case http://fogbugz.altera.com/default.asp?307450 + for {set i 0} {$i < 2} {incr i} { + set emac_fpga_enabled false + set emac_io_enabled false + + set emac_pin_mux_value [get_parameter_value EMAC${i}_PinMuxing] + set emac_ptp [get_parameter_value EMAC${i}_PTP] + + if {[string compare $emac_pin_mux_value [FPGA_MUX_VALUE]] == 0} { + set emac_fpga_enabled true + } + if {[string compare $emac_pin_mux_value "HPS I/O Set 0"] == 0} { + set emac_io_enabled true + } + + set_parameter_property EMAC${i}_PTP enabled $emac_io_enabled + + if {$emac_io_enabled && $emac_ptp } { + set instance_name peripheral_emac${i} + set atom_name hps_interface_peripheral_emac + set wys_atom_name arriav_hps_interface_peripheral_emac + set location [locations::get_fpga_location $instance_name $atom_name] + + set iface_name "emac${i}" + + fpga_interfaces::add_interface $iface_name conduit input + fpga_interfaces::add_interface_port $iface_name emac${i}_ptp_aux_ts_trig_i ptp_aux_ts_trig_i Input 1 $instance_name ptp_aux_ts_trig_i + fpga_interfaces::add_interface_port $iface_name emac${i}_ptp_pps_o ptp_pps_o Output 1 $instance_name ptp_pps_o + + + fpga_interfaces::add_module_instance $instance_name $wys_atom_name $location + } + + } +} + +proc elab_INTERRUPTS {device_family logical_view} { + set instance_name interrupts + set atom_name hps_interface_interrupts + set location [locations::get_fpga_location $instance_name $atom_name] + set any_interrupt_enabled 0 + + ##### F2H ##### + if [is_enabled F2SINTERRUPT_Enable] { + set any_interrupt_enabled 1 + set iname "f2h_irq" + set pname "f2h_irq" + if { $logical_view == 0 } { + fpga_interfaces::add_interface "${iname}0" interrupt receiver + fpga_interfaces::add_interface_port "${iname}0" "${pname}_p0" irq Input 32 + fpga_interfaces::set_port_fragments "${iname}0" "${pname}_p0" "${instance_name}:irq(31:0)" + + fpga_interfaces::add_interface "${iname}1" interrupt receiver + fpga_interfaces::add_interface_port "${iname}1" "${pname}_p1" irq Input 32 + fpga_interfaces::set_port_fragments "${iname}1" "${pname}_p1" "${instance_name}:irq(63:32)" + } + } + + ##### H2F ##### + load_h2f_interrupt_table\ + functions_by_group width_by_function inverted_by_function + + set interrupt_groups [list_h2f_interrupt_groups] + foreach group $interrupt_groups { + set parameter "S2FINTERRUPT_${group}_Enable" + set enabled [is_enabled $parameter] + + if {!$enabled} { + continue + } + set any_interrupt_enabled 1 + + foreach function $functions_by_group($group) { + set width 1 + if {[info exists width_by_function($function)]} { + set width $width_by_function($function) + } + + set suffix "" + set inverted [info exists inverted_by_function($function)] + if {$inverted} { + set suffix "_n" + } + + #skip fpga_interfaces interrupt declaration for uart + if { ($logical_view == 1) && ( + $function == "uart0" || + $function == "uart1" )} { + continue + } + + set prefix "h2f_${function}_" + set interface "${prefix}interrupt" + set port "${prefix}irq" + + if {$width > 1} { ;# for buses, use index in interface/port names + for {set i 0} {$i < $width} {incr i} { + set indexed_interface "${interface}${i}" + set indexed_port "${port}${i}${suffix}" + fpga_interfaces::add_interface\ + $indexed_interface interrupt sender + fpga_interfaces::add_interface_port\ + $indexed_interface $indexed_port irq Output 1\ + $instance_name $indexed_port + } + } else { + set port "$port${suffix}" + fpga_interfaces::add_interface\ + $interface interrupt sender + fpga_interfaces::add_interface_port\ + $interface $port irq Output 1 $instance_name $port + } + } + } + + if {$any_interrupt_enabled} { + set wys_atom_name [generic_atom_to_wys_atom $device_family $atom_name] + fpga_interfaces::add_module_instance $instance_name $wys_atom_name $location + } +} + +proc elab_TEST {device_family} { + set parameter_enabled [expr {[string compare [get_parameter_value TEST_Enable] "true" ] == 0}] + set ini_enabled [expr {[string compare [get_parameter_value quartus_ini_hps_ip_enable_test_interface] "true" ] == 0}] + + if {$parameter_enabled && $ini_enabled} { + set instance_name test_interface + set atom_name hps_interface_test + set location [locations::get_fpga_location $instance_name $atom_name] + + set iname "test" + set z "test_" + + set data [get_parameter_value test_iface_definition] + + fpga_interfaces::add_interface $iname conduit input + foreach {port width dir} $data { + fpga_interfaces::add_interface_port $iname "${z}${port}" $port $dir $width $instance_name $port + } + + set wys_atom_name [generic_atom_to_wys_atom $device_family $atom_name] + fpga_interfaces::add_module_instance $instance_name $wys_atom_name $location + } +} + +# TODO: Mode usage data +proc elab_FPGA_Peripheral_Signals {device_family} { + # disable and hide all parameters related to fpga outputs + set emac0_fpga [get_parameter_value quartus_ini_hps_ip_enable_emac0_peripheral_fpga_interface] + set lssis_fpga [get_parameter_value quartus_ini_hps_ip_enable_low_speed_serial_fpga_interfaces] + set all_fpga "true" + + set peripherals [list_peripheral_names] + foreach peripheral $peripherals { + if { [string compare $peripheral "SDIO" ] == 0 } { + continue + } + set visible false + if {[string compare $all_fpga "true" ] == 0} { + set visible true + } elseif {[string compare $emac0_fpga "true" ] == 0 && [string compare -nocase $peripheral "emac0"] == 0} { + set visible true + } elseif {[string compare $lssis_fpga "true" ] == 0 && [is_peripheral_low_speed_serial_interface $peripheral_name]} { + set visible true + } + if {[string compare -nocase $peripheral "emac0" ] == 0 || [string compare -nocase $peripheral "emac1" ] == 0} { + set visible true + } + set clocks [get_peripheral_fpga_output_clocks $peripheral] + foreach clock $clocks { + set parameter [form_peripheral_fpga_output_clock_frequency_parameter $clock] + set_parameter_property $parameter enabled false + set_parameter_property $parameter visible $visible + set clock_output_set($clock) 1 + } + + set clocks [get_peripheral_fpga_input_clocks $peripheral] + foreach clock $clocks { + set clock_input_set($clock) 1 + } + } + + array set fpga_ifaces [get_parameter_value DB_periph_ifaces] + array set iface_ports [get_parameter_value DB_iface_ports] + array set port_pins [get_parameter_value DB_port_pins] + foreach peripheral_name $fpga_ifaces([ORDERED_NAMES]) { ;# Peripherals + set pin_mux_param_name [format [PIN_MUX_PARAM_FORMAT] $peripheral_name] + set pin_mux_value [get_parameter_value $pin_mux_param_name] + set allowed_ranges [get_parameter_property $pin_mux_param_name allowed_ranges] + + if {[string compare $pin_mux_value [FPGA_MUX_VALUE]] == 0 && [lsearch $allowed_ranges [FPGA_MUX_VALUE]] != -1} { + funset peripheral + array set peripheral $fpga_ifaces($peripheral_name) + funset interfaces + array set interfaces $peripheral(interfaces) + + set instance_name [invent_peripheral_instance_name $peripheral_name] + + foreach interface_name $interfaces([ORDERED_NAMES]) { ;# Interfaces + funset interface + array set interface $interfaces($interface_name) + fpga_interfaces::add_interface $interface_name $interface(type) $interface(direction) + foreach {property_key property_value} $interface(properties) { + fpga_interfaces::set_interface_property $interface_name $property_key $property_value + } + #send_message info "NEA: peripheral_name $peripheral_name interface_name $interface_name " + + if { [string match "EMAC?" $peripheral_name] && [string match "*x_reset" $interface_name ] } { + fpga_interfaces::set_interface_property $interface_name associatedResetSinks none + } + + foreach {meta_property} [array names interface] { + # Meta Property if leading with an @ + if {[string compare [string index ${meta_property} 0] "@"] == 0} { + fpga_interfaces::set_interface_meta_property $interface_name [string replace ${meta_property} 0 0] $interface($meta_property) + } + } + + set once_per_clock 1 + funset ports + array set ports $iface_ports($interface_name) + foreach port_name $ports([ORDERED_NAMES]) { ;# Ports + funset port + array set port $ports($port_name) + + # TODO: determine width based on pins available via mode + set width [calculate_port_width $port_pins($port_name)] + + fpga_interfaces::add_interface_port $interface_name $port_name $port(role) $port(direction) $width $instance_name $port(atom_signal_name) + + set frequency 0 + # enable and show clock frequency parameters for outputs + if {[info exists clock_output_set($interface_name)]} { + set parameter [form_peripheral_fpga_output_clock_frequency_parameter $interface_name] + set_parameter_property $parameter enabled true + set frequency [get_parameter_value $parameter] + set frequency [expr {$frequency * [MHZ_TO_HZ]}] + fpga_interfaces::set_interface_property $interface_name clockRateKnown true + fpga_interfaces::set_interface_property $interface_name clockRate $frequency + } + + if {[string compare -nocase $interface(type) "clock"] == 0 && $once_per_clock} { + set once_per_clock 0 + add_clock_constraint_if_valid $frequency "*|fpga_interfaces|${instance_name}|[string tolower $port(atom_signal_name)]" + } + } + } + + # device-specific atom + set atom_name $peripheral(atom_name) + set wys_atom_name [generic_atom_to_wys_atom $device_family $atom_name] + set location [locations::get_fpga_location $peripheral_name $atom_name] + + fpga_interfaces::add_module_instance $instance_name $wys_atom_name $location + } + } +} + +# derives the WYS (device family-specific) atom name from the generic one +proc generic_atom_to_wys_atom {device_family atom_name} { + # TODO: base this on a table of data instead of on code + set result "" + if {[check_device_family_equivalence $device_family CYCLONEV]} { + set result "cyclonev_${atom_name}" + } elseif {[check_device_family_equivalence $device_family ARRIAV]} { + set result "arriav_${atom_name}" + } + return $result +} + +# invents an instance name from the peripheral's name +# assumes that the instance name is the same across a peripheral +proc invent_peripheral_instance_name {peripheral_name} { + return "peripheral_[string tolower $peripheral_name]" +} + +# TODO: do width calculation at db load time so we don't do it every elaboration! +# then make it accessible by a mode to width array for every peripheral with fpga periph interface +# TODO: also validate the static data, checking if the mode signals make sense aka only contiguous, 0-indexed mappings +proc calculate_port_width {pin_array_string} { + array set pins $pin_array_string + # TODO: -do we need to be able to support ports that don't start with pins at 0? + # -e.g. pins D0-D7 are indexed 0-7. if want D4-D7, can we do indexes 4-7? + # -for now, no! + set bit_index 0 + while {[info exists pins($bit_index)]} { + incr bit_index + } + return $bit_index +} + +proc pin_to_bank {pin} { + set io_index [string first "IO" $pin] + return [string range $pin 0 [expr {$io_index - 1}]] +} + +proc sort_pins {pins} { + set pin_suffixes [list] + foreach pin $pins { + set io_index [string first "IO" $pin] + set suffix_start [expr {$io_index + 2}] + set length [string length $pin] + set suffix [string range $pin $suffix_start [expr {$length - 1}]] + lappend pin_suffixes $suffix + } + set result [list] + set indices [lsort-indices -increasing -integer $pin_suffixes] + foreach index $indices { + lappend result [lindex $pins $index] + } + return $result +} + +proc set_peripheral_pin_muxing_description {peripheral_name pin_muxing_description mode_description} { + set parameter "[string toupper $peripheral_name]_PinMuxing" + set_display_item_property $parameter DESCRIPTION $pin_muxing_description + + set parameter "[string toupper $peripheral_name]_Mode" + set_display_item_property $parameter DESCRIPTION $mode_description +} + +# Expects same set of keys between both parameters +proc create_pin_muxing_description_table_html {signals_by_option_str pins_by_option_str} { + array set pins_by_option $pins_by_option_str + + set options [list] + foreach {option signals} $signals_by_option_str { + lappend options $option + + set pins $pins_by_option($option) + + foreach signal $signals pin $pins { + set key "${option}.${signal}" + set pins_by_option_and_signal($key) $pin + set signal_set($signal) 1 + } + } + + set sorted_signals [lsort -increasing -ascii [array names signal_set]] + set sorted_options [lsort -increasing -ascii $options] + + set ALIGN_CENTER {align="center"} + + set html "" ;# start of table, first row cell empty for signal column + foreach option $sorted_options { + set html "${html}" + } + set html "${html}" + foreach signal $sorted_signals { + set html "${html}" ;# new row w/ first cell (header) being the signal name + foreach option $sorted_options { + set key "${option}.${signal}" + if {[info exists pins_by_option_and_signal($key)]} { + set pin $pins_by_option_and_signal($key) + } else { + set pin "" + } + set html "${html}" + } + set html "${html}" + } + set html "${html}
${option}
${signal}${pin}
" + return $html +} + +proc create_mode_description_table_html {signals_by_mode_str} { + set modes [list] + + foreach {mode signals} $signals_by_mode_str { + lappend modes $mode + foreach signal $signals { + set key "${mode}.${signal}" + set membership_by_mode_and_signal($key) 1 + set signal_set($signal) 1 + } + } + + set sorted_signals [lsort -increasing -ascii [array names signal_set]] + set sorted_modes [lsort -increasing -ascii $modes] + + set ALIGN_CENTER {align="center"} + + set html "" ;# start of table, first row cell empty for signal column + foreach mode $sorted_modes { + set html "${html}" + } + set html "${html}" + foreach signal $sorted_signals { + set html "${html}" ;# new row w/ first cell (header) being the signal name + + foreach mode $sorted_modes { + set key "${mode}.${signal}" + if {[info exists membership_by_mode_and_signal($key)]} { + set member_marker "X" + } else { + set member_marker "" + } + set html "${html}" + } + set html "${html}" + } + set html "${html}
${mode}
${signal}${member_marker}
" + return $html +} + +proc get_quartus_edition {} { + set code { + set version "" + regexp {([a-zA-Z]+) (Edition|Version)$} $quartus(version) total version + return $version + } + set safe_code [string map {\n ; \t ""} $code] + set package_name "advanced_device" + set result [lindex [run_quartus_tcl_command "${package_name}:${safe_code}"] 0] + return $result +} + +proc is_soc_device {device} { + return [::pin_mux_db::verify_soc_device $device] +} + +proc set_peripheral_pin_muxing_descriptions {peripherals_ref} { + upvar 1 $peripherals_ref peripherals + + foreach peripheral_name [array names peripherals] { + set signals_by_option [list] + set pins_by_option [list] + + funset peripheral + array set peripheral $peripherals($peripheral_name) + funset pin_sets + array set pin_sets $peripheral(pin_sets) + + foreach pin_set_name [array names pin_sets] { + funset pin_set + array set pin_set $pin_sets($pin_set_name) + set signals $pin_set(signals) + lappend signals_by_option $pin_set_name $signals + set pins $pin_set(pins) + lappend pins_by_option $pin_set_name $pins + } + set signals_by_mode $peripheral(signals_by_mode) + + set table_html [create_pin_muxing_description_table_html $signals_by_option $pins_by_option] + set pin_muxing_description "" + + set table_html [create_mode_description_table_html $signals_by_mode] + set mode_description "Signal Membership Per Mode Usage Option:
${table_html}" + set_peripheral_pin_muxing_description $peripheral_name $pin_muxing_description $mode_description + } +} + +# Add pin muxing details to soc_io peripheral/signal data +add_storage_parameter pin_muxing {} +add_storage_parameter pin_muxing_check "" +proc ensure_pin_muxing_data {device_family} { + if {[check_device_family_equivalence $device_family [get_module_property SUPPORTED_DEVICE_FAMILIES]] == 0} { + return + } + + set device [get_device] + + if {![is_soc_device $device]} { + send_message error "Selected device '${device}' is not an SoC device. Please choose a valid SoC device to use the Hard Processor System." + return + } + + set device_configuration "${device_family}+${device}" + + set old_device_configuration [get_parameter_value pin_muxing_check] + if {$old_device_configuration == $device_configuration} { + return + } + + set load_rc [::pin_mux_db::load $device] + if {!$load_rc} { + send_message error "The pin information for the Hard Processor System could not be determined. Please check whether your edition of Quartus Prime supports the selected device." + return + } + locations::load $device + + load_peripherals_pin_muxing_model pin_muxing_peripherals + set_peripheral_pin_muxing_descriptions pin_muxing_peripherals + + set gpio_pins [::pin_mux_db::get_gpio_pins] + set loanio_pins [::pin_mux_db::get_loan_io_pins] + set customer_pin_names [::pin_mux_db::get_customer_pin_names] + set hlgpi_pins [::pin_mux_db::get_hlgpi_pins] + + set pin_muxing [list [array get pin_muxing_peripherals] $gpio_pins $loanio_pins $customer_pin_names $hlgpi_pins] + set_parameter_value pin_muxing $pin_muxing + set_parameter_value pin_muxing_check $device_configuration + + #### update pin_muxing data to use in java GUI #### + set pinmux_peripherals [array get pin_muxing_peripherals] + array set periph_key_value $pinmux_peripherals + + foreach {key value} [array get periph_key_value] { + set_parameter_value JAVA_${key}_DATA "$key \{$value\}" + } +} + +proc get_device {} { + + set device_name [get_parameter_value device_name] + return $device_name +} + +proc construct_hps_parameter_map {} { + set parameters [get_parameters] + foreach parameter $parameters { + set value [get_parameter_value $parameter] + set result($parameter) $value + } + return [array get result] +} + +################################################################################ +# Implements interface of util/pin_mux.tcl +# +namespace eval hps_ip_pin_muxing_model { +################################################################################ + proc get_peripherals_model {} { + set pin_muxing [get_parameter_value pin_muxing] + set peripherals [lindex $pin_muxing 0] + return $peripherals + } + proc get_emac0_fpga_ini {} { + return [is_enabled quartus_ini_hps_ip_enable_emac0_peripheral_fpga_interface] + } + proc get_lssis_fpga_ini {} { + return [is_enabled quartus_ini_hps_ip_enable_low_speed_serial_fpga_interfaces] + } + proc get_all_fpga_ini {} { + return [is_enabled quartus_ini_hps_ip_enable_all_peripheral_fpga_interfaces] + } + proc get_peripheral_pin_muxing_selection {peripheral_name} { + set pin_muxing_param_name [format [PIN_MUX_PARAM_FORMAT] $peripheral_name] + set selection [get_parameter_value $pin_muxing_param_name] + return $selection + } + proc get_peripheral_mode_selection {peripheral_name} { + set mode_param_name [format [MODE_PARAM_FORMAT] $peripheral_name] + set selection [get_parameter_value $mode_param_name] + return $selection + } + proc get_gpio_pins {} { + set pin_muxing [get_parameter_value pin_muxing] + set pins [lindex $pin_muxing 1] + return $pins + } + proc get_loanio_pins {} { + set pin_muxing [get_parameter_value pin_muxing] + set pins [lindex $pin_muxing 2] + return $pins + } + proc get_customer_pin_names {} { + set pin_muxing [get_parameter_value pin_muxing] + set pins [lindex $pin_muxing 3] + return $pins + } + proc get_hlgpi_pins {} { + set pin_muxing [get_parameter_value pin_muxing] + set pins [lindex $pin_muxing 4] + return $pins + } + proc get_unsupported_peripheral {peripheral_name} { + set device_family [get_parameter_value hps_device_family] + set skip 0 + if {[check_device_family_equivalence $device_family ARRIAV]} { + foreach excluded_peripheral [ARRIAV_EXCLUDED_PERIPHRERALS] { + if {[string compare $excluded_peripheral $peripheral_name] == 0} { + set skip 1 + } + } + } + return $skip + } +} + + +## Add documentation links for user guide and/or release notes +add_documentation_link "User Guide" https://www.altera.com/products/soc/overview.html diff --git a/sys/ip/reset_source.v b/sys/ip/reset_source.v new file mode 100644 index 0000000..e9f0435 --- /dev/null +++ b/sys/ip/reset_source.v @@ -0,0 +1,48 @@ +// reset_source.v + +// This file was auto-generated as a prototype implementation of a module +// created in component editor. It ties off all outputs to ground and +// ignores all inputs. It needs to be edited to make it do something +// useful. +// +// This file will not be automatically regenerated. You should check it in +// to your version control system if you want to keep it. + +`timescale 1 ps / 1 ps +module reset_source +( + input wire clk, // clock.clk + input wire reset_hps, // reset_hps.reset + output wire reset_sys, // reset_sys.reset + output wire reset_cold, // reset_cold.reset + input wire cold_req, // reset_ctl.cold_req + output wire reset, // .reset + input wire reset_req, // .reset_req + input wire warm_req, // .warm_req + output wire reset_warm // reset_warm.reset +); + +assign reset_cold = cold_req; +assign reset_warm = warm_req; + +assign reset = reset_sys; +assign reset_sys = sys_reset | reset_hps | reset_req; + +reg sys_reset = 1; +always @(posedge clk) begin + integer timeout = 0; + reg reset_lock = 0; + + reset_lock <= reset_lock | cold_req; + + if(timeout < 2000000) begin + sys_reset <= 1; + timeout <= timeout + 1; + reset_lock <= 0; + end + else begin + sys_reset <= reset_lock; + end +end + +endmodule diff --git a/sys/ip/reset_source_hw.tcl b/sys/ip/reset_source_hw.tcl new file mode 100644 index 0000000..528bdf6 --- /dev/null +++ b/sys/ip/reset_source_hw.tcl @@ -0,0 +1,151 @@ +# TCL File Generated by Component Editor 16.1 +# Thu Apr 20 14:20:36 CST 2017 +# DO NOT MODIFY + + +# +# reset_source "reset_source" v1.0 +# Sorgelig 2017.04.20.14:20:36 +# +# + +# +# request TCL package from ACDS 16.1 +# +package require -exact qsys 16.1 + + +# +# module reset_source +# +set_module_property DESCRIPTION "" +set_module_property NAME reset_source +set_module_property VERSION 1.0 +set_module_property INTERNAL false +set_module_property OPAQUE_ADDRESS_MAP true +set_module_property AUTHOR Sorgelig +set_module_property DISPLAY_NAME reset_source +set_module_property INSTANTIATE_IN_SYSTEM_MODULE true +set_module_property EDITABLE true +set_module_property REPORT_TO_TALKBACK false +set_module_property ALLOW_GREYBOX_GENERATION false +set_module_property REPORT_HIERARCHY false + + +# +# file sets +# +add_fileset QUARTUS_SYNTH QUARTUS_SYNTH "" "" +set_fileset_property QUARTUS_SYNTH TOP_LEVEL reset_source +set_fileset_property QUARTUS_SYNTH ENABLE_RELATIVE_INCLUDE_PATHS false +set_fileset_property QUARTUS_SYNTH ENABLE_FILE_OVERWRITE_MODE true +add_fileset_file reset_source.v VERILOG PATH reset_source.v TOP_LEVEL_FILE + + +# +# parameters +# + + +# +# display items +# + + +# +# connection point clock +# +add_interface clock clock end +set_interface_property clock clockRate 0 +set_interface_property clock ENABLED true +set_interface_property clock EXPORT_OF "" +set_interface_property clock PORT_NAME_MAP "" +set_interface_property clock CMSIS_SVD_VARIABLES "" +set_interface_property clock SVD_ADDRESS_GROUP "" + +add_interface_port clock clk clk Input 1 + + +# +# connection point reset_hps +# +add_interface reset_hps reset end +set_interface_property reset_hps associatedClock "" +set_interface_property reset_hps synchronousEdges NONE +set_interface_property reset_hps ENABLED true +set_interface_property reset_hps EXPORT_OF "" +set_interface_property reset_hps PORT_NAME_MAP "" +set_interface_property reset_hps CMSIS_SVD_VARIABLES "" +set_interface_property reset_hps SVD_ADDRESS_GROUP "" + +add_interface_port reset_hps reset_hps reset Input 1 + + +# +# connection point reset_sys +# +add_interface reset_sys reset start +set_interface_property reset_sys associatedClock "" +set_interface_property reset_sys associatedDirectReset "" +set_interface_property reset_sys associatedResetSinks "" +set_interface_property reset_sys synchronousEdges NONE +set_interface_property reset_sys ENABLED true +set_interface_property reset_sys EXPORT_OF "" +set_interface_property reset_sys PORT_NAME_MAP "" +set_interface_property reset_sys CMSIS_SVD_VARIABLES "" +set_interface_property reset_sys SVD_ADDRESS_GROUP "" + +add_interface_port reset_sys reset_sys reset Output 1 + + +# +# connection point reset_ctl +# +add_interface reset_ctl conduit end +set_interface_property reset_ctl associatedClock "" +set_interface_property reset_ctl associatedReset "" +set_interface_property reset_ctl ENABLED true +set_interface_property reset_ctl EXPORT_OF "" +set_interface_property reset_ctl PORT_NAME_MAP "" +set_interface_property reset_ctl CMSIS_SVD_VARIABLES "" +set_interface_property reset_ctl SVD_ADDRESS_GROUP "" + +add_interface_port reset_ctl cold_req cold_req Input 1 +add_interface_port reset_ctl reset reset Output 1 +add_interface_port reset_ctl reset_req reset_req Input 1 +add_interface_port reset_ctl warm_req warm_req Input 1 + + +# +# connection point reset_warm +# +add_interface reset_warm reset start +set_interface_property reset_warm associatedClock "" +set_interface_property reset_warm associatedDirectReset "" +set_interface_property reset_warm associatedResetSinks "" +set_interface_property reset_warm synchronousEdges NONE +set_interface_property reset_warm ENABLED true +set_interface_property reset_warm EXPORT_OF "" +set_interface_property reset_warm PORT_NAME_MAP "" +set_interface_property reset_warm CMSIS_SVD_VARIABLES "" +set_interface_property reset_warm SVD_ADDRESS_GROUP "" + +add_interface_port reset_warm reset_warm reset Output 1 + + +# +# connection point reset_cold +# +add_interface reset_cold reset start +set_interface_property reset_cold associatedClock "" +set_interface_property reset_cold associatedDirectReset "" +set_interface_property reset_cold associatedResetSinks "" +set_interface_property reset_cold synchronousEdges NONE +set_interface_property reset_cold ENABLED true +set_interface_property reset_cold EXPORT_OF "" +set_interface_property reset_cold PORT_NAME_MAP "" +set_interface_property reset_cold CMSIS_SVD_VARIABLES "" +set_interface_property reset_cold SVD_ADDRESS_GROUP "" + +add_interface_port reset_cold reset_cold reset Output 1 + diff --git a/sys/lpf48k.sv b/sys/lpf48k.sv new file mode 100644 index 0000000..2a32981 --- /dev/null +++ b/sys/lpf48k.sv @@ -0,0 +1,100 @@ +// low pass filter +// Revision 1.00 +// +// Copyright (c) 2008 Takayuki Hara. +// All rights reserved. +// +// Redistribution and use of this source code or any derivative works, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// 2. 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. +// 3. Redistributions may not be sold, nor may they be used in a commercial +// product or activity without specific prior written permission. +// +// 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 OWNER 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. +// +// +// LPF (cut off 48kHz at 3.58MHz) + +module lpf48k #(parameter MSB = 15) +( + input RESET, + input CLK, + input CE, + input ENABLE, + + input [MSB:0] IDATA, + output [MSB:0] ODATA +); + +wire [7:0] LPF_TAP_DATA[0:71] = +'{ + 8'h51, 8'h07, 8'h07, 8'h08, 8'h08, 8'h08, 8'h09, 8'h09, + 8'h09, 8'h0A, 8'h0A, 8'h0A, 8'h0A, 8'h0B, 8'h0B, 8'h0B, + 8'h0B, 8'h0C, 8'h0C, 8'h0C, 8'h0C, 8'h0D, 8'h0D, 8'h0D, + 8'h0D, 8'h0D, 8'h0D, 8'h0E, 8'h0E, 8'h0E, 8'h0E, 8'h0E, + 8'h0E, 8'h0E, 8'h0E, 8'h0E, 8'h0E, 8'h0E, 8'h0E, 8'h0E, + 8'h0E, 8'h0E, 8'h0E, 8'h0E, 8'h0E, 8'h0D, 8'h0D, 8'h0D, + 8'h0D, 8'h0D, 8'h0D, 8'h0C, 8'h0C, 8'h0C, 8'h0C, 8'h0B, + 8'h0B, 8'h0B, 8'h0B, 8'h0A, 8'h0A, 8'h0A, 8'h0A, 8'h09, + 8'h09, 8'h09, 8'h08, 8'h08, 8'h08, 8'h07, 8'h07, 8'h51 +}; + +reg [7:0] FF_ADDR = 0; +reg [MSB+10:0] FF_INTEG = 0; +wire [MSB+8:0] W_DATA; +wire W_ADDR_END; + +assign W_ADDR_END = ((FF_ADDR == 71)); + +reg [MSB:0] OUT; + +assign ODATA = ENABLE ? OUT : IDATA; + +always @(posedge RESET or posedge CLK) begin + if (RESET) FF_ADDR <= 0; + else + begin + if (CE) begin + if (W_ADDR_END) FF_ADDR <= 0; + else FF_ADDR <= FF_ADDR + 1'd1; + end + end +end + +assign W_DATA = LPF_TAP_DATA[FF_ADDR] * IDATA; + +always @(posedge RESET or posedge CLK) begin + if (RESET) FF_INTEG <= 0; + else + begin + if (CE) begin + if (W_ADDR_END) FF_INTEG <= 0; + else FF_INTEG <= FF_INTEG + W_DATA; + end + end +end + +always @(posedge RESET or posedge CLK) begin + if (RESET) OUT <= 0; + else + begin + if (CE && W_ADDR_END) OUT <= FF_INTEG[MSB + 10:10]; + end +end + +endmodule diff --git a/sys/osd.v b/sys/osd.v new file mode 100644 index 0000000..87a2eff --- /dev/null +++ b/sys/osd.v @@ -0,0 +1,168 @@ +// A simple OSD implementation. Can be hooked up between a cores +// VGA output and the physical VGA pins + +module osd +( + input clk_sys, + + input io_osd, + input io_strobe, + input [7:0] io_din, + + input clk_video, + input [23:0] din, + output [23:0] dout, + input de +); + +parameter OSD_COLOR = 3'd4; +parameter OSD_X_OFFSET = 12'd0; +parameter OSD_Y_OFFSET = 12'd0; + +localparam OSD_WIDTH = 12'd256; +localparam OSD_HEIGHT = 12'd64; + +// this core supports only the display related OSD commands +// of the minimig v1 +reg osd_enable; +(* ramstyle = "no_rw_check" *) reg [7:0] osd_buffer[4096]; // the OSD buffer itself + +reg highres = 0; + +// the OSD has its own SPI interface to the io controller +always@(posedge clk_sys) begin + reg [11:0] bcnt; + reg [7:0] cmd; + reg has_cmd; + reg old_strobe; + + old_strobe <= io_strobe; + + if(~io_osd) begin + bcnt <= 0; + has_cmd <= 0; + end else begin + if(~old_strobe & io_strobe) begin + if(!has_cmd) begin + has_cmd <= 1; + cmd <= io_din; + // command 0x40: OSDCMDENABLE, OSDCMDDISABLE + if(io_din[7:4] == 4'b0100) begin + osd_enable <= io_din[0]; + if(!io_din[0]) highres <= 0; + end + bcnt <= {io_din[3:0], 8'h00}; + if(io_din[7:3] == 5'b00101) highres <= 1; + end else begin + // command 0x20: OSDCMDWRITE + if(cmd[7:4] == 4'b0010) begin + osd_buffer[bcnt] <= io_din; + bcnt <= bcnt + 1'd1; + end + end + end + end +end + +reg ce_pix; +always @(negedge clk_video) begin + integer cnt = 0; + integer pixsz, pixcnt; + reg deD; + + cnt <= cnt + 1; + deD <= de; + + pixcnt <= pixcnt + 1; + if(pixcnt == pixsz) pixcnt <= 0; + ce_pix <= !pixcnt; + + if(~deD && de) cnt <= 0; + + if(deD && ~de) begin + pixsz <= (((cnt+1'b1) >> 9) > 1) ? (((cnt+1'b1) >> 9) - 1) : 0; + pixcnt <= 0; + end +end + +reg [23:0] h_cnt; +reg [21:0] v_cnt; +reg [21:0] dsp_width; +reg [21:0] dsp_height; +reg [7:0] osd_byte; +reg [21:0] osd_vcnt; +reg [21:0] fheight; + +wire [21:0] hrheight = (OSD_HEIGHT< {dsp_width, 2'b00}) begin + v_cnt <= 0; + dsp_height <= v_cnt; + + if(v_cnt<320) begin + multiscan <= 0; + fheight <= hrheight; + end + else if(v_cnt<640) begin + multiscan <= 1; + fheight <= hrheight << 1; + end + else if(v_cnt<960) begin + multiscan <= 2; + fheight <= hrheight + (hrheight<<1); + end + else begin + multiscan <= 3; + fheight <= hrheight << 2; + end + end + h_cnt <= 0; + + osd_div <= osd_div + 1'd1; + if(osd_div == multiscan) begin + osd_div <= 0; + osd_vcnt <= osd_vcnt + 1'd1; + end + if(v_osd_start == (v_cnt+1'b1)) {osd_div, osd_vcnt} <= 0; + end + + osd_byte <= osd_buffer[{osd_vcnt[6:3], osd_hcnt[7:0]}]; + end +end + +// area in which OSD is being displayed +wire [21:0] h_osd_start = ((dsp_width - OSD_WIDTH)>>1) + OSD_X_OFFSET; +wire [21:0] h_osd_end = h_osd_start + OSD_WIDTH; +wire [21:0] v_osd_start = ((dsp_height- fheight)>>1) + OSD_Y_OFFSET; +wire [21:0] v_osd_end = v_osd_start + fheight; + +wire [21:0] osd_hcnt = h_cnt[21:0] - h_osd_start + 1'd1; + +wire osd_de = osd_enable && + (h_cnt >= h_osd_start) && (h_cnt < h_osd_end) && + (v_cnt >= v_osd_start) && (v_cnt < v_osd_end); + +wire osd_pixel = osd_byte[osd_vcnt[2:0]]; + + +assign dout = !osd_de ? din : {{osd_pixel, osd_pixel, OSD_COLOR[2], din[23:19]}, + {osd_pixel, osd_pixel, OSD_COLOR[1], din[15:11]}, + {osd_pixel, osd_pixel, OSD_COLOR[0], din[7:3]}}; + +endmodule diff --git a/sys/pattern_vg.v b/sys/pattern_vg.v new file mode 100644 index 0000000..6379278 --- /dev/null +++ b/sys/pattern_vg.v @@ -0,0 +1,120 @@ +module pattern_vg +#( + parameter B=8, // number of bits per channel + X_BITS=13, + Y_BITS=13, + FRACTIONAL_BITS = 12 +) + +( + input reset, clk_in, + input wire [X_BITS-1:0] x, + input wire [Y_BITS-1:0] y, + input wire vn_in, hn_in, dn_in, + input wire [B-1:0] r_in, g_in, b_in, + output reg vn_out, hn_out, den_out, + output reg [B-1:0] r_out, g_out, b_out, + input wire [X_BITS-1:0] total_active_pix, + input wire [Y_BITS-1:0] total_active_lines, + input wire [7:0] pattern, + input wire [B+FRACTIONAL_BITS-1:0] ramp_step +); + +reg [B+FRACTIONAL_BITS-1:0] ramp_values; // 12-bit fractional end for ramp values + + +//wire bar_0 = y<90; +wire bar_1 = y>=90 & y<180; +wire bar_2 = y>=180 & y<270; +wire bar_3 = y>=270 & y<360; +wire bar_4 = y>=360 & y<450; +wire bar_5 = y>=450 & y<540; +wire bar_6 = y>=540 & y<630; +wire bar_7 = y>=630 & y<720; + + +wire red_enable = bar_1 | bar_3 | bar_5 | bar_7; +wire green_enable = bar_2 | bar_3 | bar_6 | bar_7; +wire blue_enable = bar_4 | bar_5 | bar_6 | bar_7; + +always @(posedge clk_in) + begin + vn_out <= vn_in; + hn_out <= hn_in; + den_out <= dn_in; + if (reset) + ramp_values <= 0; + else if (pattern == 8'b0) // no pattern + begin + r_out <= r_in; + g_out <= g_in; + b_out <= b_in; + end + else if (pattern == 8'b1) // border + begin + if (dn_in && ((y == 12'b0) || (x == 12'b0) || (x == total_active_pix - 1) || (y == total_active_lines - 1))) + begin + r_out <= 8'hFF; + g_out <= 8'hFF; + b_out <= 8'hFF; + end + else // Double-border (OzOnE)... + if (dn_in && ((y == 12'b0+20) || (x == 12'b0+20) || (x == total_active_pix - 1 - 20) || (y == total_active_lines - 1 - 20))) + begin + r_out <= 8'hD0; + g_out <= 8'hB0; + b_out <= 8'hB0; + end + else + begin + r_out <= r_in; + g_out <= g_in; + b_out <= b_in; + end + end + else if (pattern == 8'd2) // moireX + begin + if ((dn_in) && x[0] == 1'b1) + begin + r_out <= 8'hFF; + g_out <= 8'hFF; + b_out <= 8'hFF; + end + else + begin + r_out <= 8'b0; + g_out <= 8'b0; + b_out <= 8'b0; + end + end + else if (pattern == 8'd3) // moireY + begin + if ((dn_in) && y[0] == 1'b1) + begin + r_out <= 8'hFF; + g_out <= 8'hFF; + b_out <= 8'hFF; + end + else + begin + r_out <= 8'b0; + g_out <= 8'b0; + b_out <= 8'b0; + end + end + else if (pattern == 8'd4) // Simple RAMP + begin + r_out <= (red_enable) ? ramp_values[B+FRACTIONAL_BITS-1:FRACTIONAL_BITS] : 8'h00; + g_out <= (green_enable) ? ramp_values[B+FRACTIONAL_BITS-1:FRACTIONAL_BITS] : 8'h00; + b_out <= (blue_enable) ? ramp_values[B+FRACTIONAL_BITS-1:FRACTIONAL_BITS] : 8'h00; + + if ((x == total_active_pix - 1) && (dn_in)) + ramp_values <= 0; + else if ((x == 0) && (dn_in)) + ramp_values <= ramp_step; + else if (dn_in) + ramp_values <= ramp_values + ramp_step; + end +end + +endmodule diff --git a/sys/pll.qip b/sys/pll.qip new file mode 100644 index 0000000..a3d2d53 --- /dev/null +++ b/sys/pll.qip @@ -0,0 +1,337 @@ +set_global_assignment -entity "pll" -library "pll" -name IP_TOOL_NAME "altera_pll" +set_global_assignment -entity "pll" -library "pll" -name IP_TOOL_VERSION "17.0" +set_global_assignment -entity "pll" -library "pll" -name IP_TOOL_ENV "mwpim" +set_global_assignment -library "pll" -name MISC_FILE [file join $::quartus(qip_path) "pll.cmp"] +set_global_assignment -entity "pll" -library "pll" -name IP_TARGETED_DEVICE_FAMILY "Cyclone V" +set_global_assignment -entity "pll" -library "pll" -name IP_GENERATED_DEVICE_FAMILY "{Cyclone V}" +set_global_assignment -entity "pll" -library "pll" -name IP_QSYS_MODE "UNKNOWN" +set_global_assignment -name SYNTHESIS_ONLY_QIP ON +set_global_assignment -entity "pll" -library "pll" -name IP_COMPONENT_NAME "cGxs" +set_global_assignment -entity "pll" -library "pll" -name IP_COMPONENT_DISPLAY_NAME "QWx0ZXJhIFBMTA==" +set_global_assignment -entity "pll" -library "pll" -name IP_COMPONENT_REPORT_HIERARCHY "Off" +set_global_assignment -entity "pll" -library "pll" -name IP_COMPONENT_INTERNAL "Off" +set_global_assignment -entity "pll" -library "pll" -name IP_COMPONENT_AUTHOR "QWx0ZXJhIENvcnBvcmF0aW9u" +set_global_assignment -entity "pll" -library "pll" -name IP_COMPONENT_VERSION "MTcuMA==" +set_global_assignment -entity "pll" -library "pll" -name IP_COMPONENT_DESCRIPTION "QWx0ZXJhIFBoYXNlLUxvY2tlZCBMb29wIChBTFRFUkFfUExMKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_NAME "cGxsXzAwMDI=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_DISPLAY_NAME "QWx0ZXJhIFBMTA==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_REPORT_HIERARCHY "Off" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_INTERNAL "Off" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_AUTHOR "QWx0ZXJhIENvcnBvcmF0aW9u" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_VERSION "MTcuMA==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_DESCRIPTION "QWx0ZXJhIFBoYXNlLUxvY2tlZCBMb29wIChBTFRFUkFfUExMKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZGVidWdfcHJpbnRfb3V0cHV0::ZmFsc2U=::ZGVidWdfcHJpbnRfb3V0cHV0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZGVidWdfdXNlX3JiY190YWZfbWV0aG9k::ZmFsc2U=::ZGVidWdfdXNlX3JiY190YWZfbWV0aG9k" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZGV2aWNl::NUNFQkEyRjE3QTc=::ZGV2aWNl" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BsbF9tb2Rl::RnJhY3Rpb25hbC1OIFBMTA==::UExMIE1vZGU=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZnJhY3Rpb25hbF92Y29fbXVsdGlwbGllcg==::dHJ1ZQ==::ZnJhY3Rpb25hbF92Y29fbXVsdGlwbGllcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3JlZmVyZW5jZV9jbG9ja19mcmVxdWVuY3k=::NTAuMA==::UmVmZXJlbmNlIENsb2NrIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cmVmZXJlbmNlX2Nsb2NrX2ZyZXF1ZW5jeQ==::NTAuMCBNSHo=::cmVmZXJlbmNlX2Nsb2NrX2ZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2NoYW5uZWxfc3BhY2luZw==::MC4w::Q2hhbm5lbCBTcGFjaW5n" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX29wZXJhdGlvbl9tb2Rl::ZGlyZWN0::T3BlcmF0aW9uIE1vZGU=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2ZlZWRiYWNrX2Nsb2Nr::R2xvYmFsIENsb2Nr::RmVlZGJhY2sgQ2xvY2s=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2ZyYWN0aW9uYWxfY291dA==::MzI=::RnJhY3Rpb25hbCBjYXJyeSBvdXQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RzbV9vdXRfc2Vs::MXN0X29yZGVy::RFNNIE9yZGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3BlcmF0aW9uX21vZGU=::ZGlyZWN0::b3BlcmF0aW9uX21vZGU=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3VzZV9sb2NrZWQ=::dHJ1ZQ==::RW5hYmxlIGxvY2tlZCBvdXRwdXQgcG9ydA==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX2Fkdl9wYXJhbXM=::ZmFsc2U=::RW5hYmxlIHBoeXNpY2FsIG91dHB1dCBjbG9jayBwYXJhbWV0ZXJz" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX251bWJlcl9vZl9jbG9ja3M=::Mg==::TnVtYmVyIE9mIENsb2Nrcw==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "bnVtYmVyX29mX2Nsb2Nrcw==::Mg==::bnVtYmVyX29mX2Nsb2Nrcw==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX211bHRpcGx5X2ZhY3Rvcg==::MTM=::TXVsdGlwbHkgRmFjdG9yIChNLUNvdW50ZXIp" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2ZyYWNfbXVsdGlwbHlfZmFjdG9y::MQ==::RnJhY3Rpb25hbCBNdWx0aXBseSBGYWN0b3IgKEsp" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3Jfbg==::MQ==::RGl2aWRlIEZhY3RvciAoTi1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjA=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kw::NjIuNjY4OA==::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzA=::MTA=::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iw::MTM=::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjA=::MzM4MDcyMzM3OA==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMA==::MTE=::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MA==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzA=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDA=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUw::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kx::NjIuNjY4OA==::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE=::MTA=::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Ix::MTM=::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE=::MzM4MDcyMzM3OA==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMQ==::MTE=::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MQ==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMQ==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MQ==::LTQzNTI=::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE=::MTgwLjA=::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUx::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjI=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3ky::MzIuNQ==::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzI=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iy::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjI=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMg==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Mg==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMg==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Mg==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzI=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDI=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUy::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjM=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kz::OC4xMjU=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzM=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iz::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjM=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMw==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Mw==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMw==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Mw==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzM=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDM=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUz::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjQ=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k0::NDguMA==::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzQ=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I0::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjQ=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNA==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5NA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0NA==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzQ=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDQ=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU0::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjU=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k1::OC4zMzM=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzU=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I1::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjU=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNQ==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5NQ==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNQ==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0NQ==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzU=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDU=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU1::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjY=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k2::OC4w::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzY=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I2::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjY=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNg==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Ng==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNg==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Ng==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzY=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDY=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU2::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjc=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k3::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzc=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I3::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3Rvcjc=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNw==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Nw==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNw==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Nw==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzc=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDc=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU3::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjg=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k4::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzg=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I4::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3Rvcjg=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yOA==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5OA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzOA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0OA==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzg=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDg=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU4::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjk=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k5::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzk=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I5::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3Rvcjk=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yOQ==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5OQ==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzOQ==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0OQ==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzk=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDk=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU5::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEw::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMA==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEw::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMA==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEw::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTA=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTA=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTA=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTA=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEw::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEw::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMA==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEx::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMQ==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEx::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMQ==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEx::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTE=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTE=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTE=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTE=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEx::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEx::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMQ==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEy::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMg==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEy::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMg==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEy::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTI=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTI=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTI=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTI=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEy::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEy::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMg==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEz::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMw==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEz::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMw==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEz::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTM=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTM=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTM=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTM=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEz::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEz::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMw==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE0::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNA==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE0::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNA==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE0::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTQ=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTQ=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTQ=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTQ=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE0::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE0::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNA==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE1::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNQ==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE1::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNQ==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE1::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTU=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTU=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTU=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTU=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE1::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE1::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNQ==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE2::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNg==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE2::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNg==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE2::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTY=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTY=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTY=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTY=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE2::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE2::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNg==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE3::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNw==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE3::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNw==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE3::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTc=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTc=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTc=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTc=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE3::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE3::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNw==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTA=::NjIuNjY4ODAwIE1Ieg==::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTA=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQw::MCBwcw==::cGhhc2Vfc2hpZnQw" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTA=::NTA=::ZHV0eV9jeWNsZTA=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE=::NjIuNjY4ODAwIE1Ieg==::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQx::LTQzNTEgcHM=::cGhhc2Vfc2hpZnQx" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE=::NTA=::ZHV0eV9jeWNsZTE=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTI=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTI=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQy::MCBwcw==::cGhhc2Vfc2hpZnQy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTI=::NTA=::ZHV0eV9jeWNsZTI=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTM=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQz::MCBwcw==::cGhhc2Vfc2hpZnQz" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTM=::NTA=::ZHV0eV9jeWNsZTM=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTQ=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ0::MCBwcw==::cGhhc2Vfc2hpZnQ0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTQ=::NTA=::ZHV0eV9jeWNsZTQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTU=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTU=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ1::MCBwcw==::cGhhc2Vfc2hpZnQ1" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTU=::NTA=::ZHV0eV9jeWNsZTU=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTY=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTY=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ2::MCBwcw==::cGhhc2Vfc2hpZnQ2" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTY=::NTA=::ZHV0eV9jeWNsZTY=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTc=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTc=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ3::MCBwcw==::cGhhc2Vfc2hpZnQ3" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTc=::NTA=::ZHV0eV9jeWNsZTc=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTg=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTg=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ4::MCBwcw==::cGhhc2Vfc2hpZnQ4" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTg=::NTA=::ZHV0eV9jeWNsZTg=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTk=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTk=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ5::MCBwcw==::cGhhc2Vfc2hpZnQ5" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTk=::NTA=::ZHV0eV9jeWNsZTk=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEw::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEw" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMA==::MCBwcw==::cGhhc2Vfc2hpZnQxMA==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEw::NTA=::ZHV0eV9jeWNsZTEw" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEx::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEx" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMQ==::MCBwcw==::cGhhc2Vfc2hpZnQxMQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEx::NTA=::ZHV0eV9jeWNsZTEx" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEy::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMg==::MCBwcw==::cGhhc2Vfc2hpZnQxMg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEy::NTA=::ZHV0eV9jeWNsZTEy" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEz::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEz" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMw==::MCBwcw==::cGhhc2Vfc2hpZnQxMw==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEz::NTA=::ZHV0eV9jeWNsZTEz" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE0::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNA==::MCBwcw==::cGhhc2Vfc2hpZnQxNA==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE0::NTA=::ZHV0eV9jeWNsZTE0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE1::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE1" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNQ==::MCBwcw==::cGhhc2Vfc2hpZnQxNQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE1::NTA=::ZHV0eV9jeWNsZTE1" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE2::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE2" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNg==::MCBwcw==::cGhhc2Vfc2hpZnQxNg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE2::NTA=::ZHV0eV9jeWNsZTE2" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE3::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE3" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNw==::MCBwcw==::cGhhc2Vfc2hpZnQxNw==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE3::NTA=::ZHV0eV9jeWNsZTE3" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BsbF9hdXRvX3Jlc2V0::T24=::UExMIEF1dG8gUmVzZXQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BsbF9iYW5kd2lkdGhfcHJlc2V0::QXV0bw==::UExMIEJhbmR3aWR0aCBQcmVzZXQ=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX3JlY29uZg==::ZmFsc2U=::RW5hYmxlIGR5bmFtaWMgcmVjb25maWd1cmF0aW9uIG9mIFBMTA==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX2Rwc19wb3J0cw==::ZmFsc2U=::RW5hYmxlIGFjY2VzcyB0byBkeW5hbWljIHBoYXNlIHNoaWZ0IHBvcnRz" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX3Bob3V0X3BvcnRz::ZmFsc2U=::RW5hYmxlIGFjY2VzcyB0byBQTEwgRFBBIG91dHB1dCBwb3J0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGxsX3R5cGU=::R2VuZXJhbA==::UExMIFRZUEU=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGxsX3N1YnR5cGU=::R2VuZXJhbA==::UExMIFNVQlRZUEU=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BhcmFtZXRlcl9saXN0::TS1Db3VudGVyIEhpIERpdmlkZSxNLUNvdW50ZXIgTG93IERpdmlkZSxOLUNvdW50ZXIgSGkgRGl2aWRlLE4tQ291bnRlciBMb3cgRGl2aWRlLE0tQ291bnRlciBCeXBhc3MgRW5hYmxlLE4tQ291bnRlciBCeXBhc3MgRW5hYmxlLE0tQ291bnRlciBPZGQgRGl2aWRlIEVuYWJsZSxOLUNvdW50ZXIgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTAgSGkgRGl2aWRlLEMtQ291bnRlci0wIExvdyBEaXZpZGUsQy1Db3VudGVyLTAgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci0wIFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTAgSW5wdXQgU291cmNlLEMtQ291bnRlci0wIEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTAgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTEgSGkgRGl2aWRlLEMtQ291bnRlci0xIExvdyBEaXZpZGUsQy1Db3VudGVyLTEgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci0xIFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTEgSW5wdXQgU291cmNlLEMtQ291bnRlci0xIEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTEgT2RkIERpdmlkZSBFbmFibGUsVkNPIFBvc3QgRGl2aWRlIENvdW50ZXIgRW5hYmxlLENoYXJnZSBQdW1wIGN1cnJlbnQgKHVBKSxMb29wIEZpbHRlciBCYW5kd2lkdGggUmVzaXN0b3IgKE9obXMpICxQTEwgT3V0cHV0IFZDTyBGcmVxdWVuY3ksSy1GcmFjdGlvbmFsIERpdmlzaW9uIFZhbHVlIChEU00pLEZlZWRiYWNrIENsb2NrIFR5cGUsRmVlZGJhY2sgQ2xvY2sgTVVYIDEsRmVlZGJhY2sgQ2xvY2sgTVVYIDIsTSBDb3VudGVyIFNvdXJjZSBNVVgsUExMIEF1dG8gUmVzZXQ=::UGFyYW1ldGVyIE5hbWVz" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3BhcmFtZXRlcl92YWx1ZXM=::Nyw2LDI1NiwyNTYsZmFsc2UsdHJ1ZSx0cnVlLGZhbHNlLDYsNSwxLDAscGhfbXV4X2NsayxmYWxzZSx0cnVlLDYsNSw5LDAscGhfbXV4X2NsayxmYWxzZSx0cnVlLDEsMzAsMjAwMCw2ODkuMzU2OCBNSHosMzM4MDcyMzM3OCxub25lLGdsYixtX2NudCxwaF9tdXhfY2xrLHRydWU=::UGFyYW1ldGVyIFZhbHVlcw==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX21pZl9nZW5lcmF0ZQ==::ZmFsc2U=::R2VuZXJhdGUgTUlGIGZpbGU=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9taWZfZHBz::ZmFsc2U=::RW5hYmxlIER5bmFtaWMgUGhhc2UgU2hpZnQgZm9yIE1JRiBzdHJlYW1pbmc=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Rwc19jbnRy::QzA=::RFBTIENvdW50ZXIgU2VsZWN0aW9u" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Rwc19udW0=::MQ==::TnVtYmVyIG9mIER5bmFtaWMgUGhhc2UgU2hpZnRz" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2Rwc19kaXI=::UG9zaXRpdmU=::RHluYW1pYyBQaGFzZSBTaGlmdCBEaXJlY3Rpb24=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX3JlZmNsa19zd2l0Y2g=::ZmFsc2U=::Q3JlYXRlIGEgc2Vjb25kIGlucHV0IGNsayAncmVmY2xrMSc=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9jYXNjYWRlX291dA==::ZmFsc2U=::Q3JlYXRlIGEgJ2Nhc2NhZGVfb3V0JyBzaWduYWwgdG8gY29ubmVjdCB3aXRoIGEgZG93bnN0cmVhbSBQTEw=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9jYXNjYWRlX2lu::ZmFsc2U=::Q3JlYXRlIGFuIGFkanBsbGluIG9yIGNjbGsgc2lnbmFsIHRvIGNvbm5lY3Qgd2l0aCBhbiB1cHN0cmVhbSBQTEw=" + +set_global_assignment -library "pll" -name VERILOG_FILE [file join $::quartus(qip_path) "pll.v"] +set_global_assignment -library "pll" -name VERILOG_FILE [file join $::quartus(qip_path) "pll/pll_0002.v"] +set_global_assignment -library "pll" -name QIP_FILE [file join $::quartus(qip_path) "pll/pll_0002.qip"] + +set_global_assignment -entity "pll_0002" -library "pll" -name IP_TOOL_NAME "altera_pll" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_TOOL_VERSION "17.0" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_TOOL_ENV "mwpim" diff --git a/sys/pll.v b/sys/pll.v new file mode 100644 index 0000000..66f7b1e --- /dev/null +++ b/sys/pll.v @@ -0,0 +1,255 @@ +// megafunction wizard: %Altera PLL v17.0% +// GENERATION: XML +// pll.v + +// Generated using ACDS version 17.0 598 + +`timescale 1 ps / 1 ps +module pll ( + input wire refclk, // refclk.clk + input wire rst, // reset.reset + output wire outclk_0, // outclk0.clk + output wire outclk_1, // outclk1.clk + output wire locked // locked.export + ); + + pll_0002 pll_inst ( + .refclk (refclk), // refclk.clk + .rst (rst), // reset.reset + .outclk_0 (outclk_0), // outclk0.clk + .outclk_1 (outclk_1), // outclk1.clk + .locked (locked) // locked.export + ); + +endmodule +// Retrieval info: +// +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// IPFS_FILES : pll.vo +// RELATED_FILES: pll.v, pll_0002.v diff --git a/sys/pll/pll_0002.qip b/sys/pll/pll_0002.qip new file mode 100644 index 0000000..9f8ded1 --- /dev/null +++ b/sys/pll/pll_0002.qip @@ -0,0 +1,4 @@ +set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*pll_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_CHANNEL_SPACING "0.0 KHz" -to "*pll_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_AUTO_RESET ON -to "*pll_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*pll_0002*|altera_pll:altera_pll_i*|*" diff --git a/sys/pll/pll_0002.v b/sys/pll/pll_0002.v new file mode 100644 index 0000000..d71c89b --- /dev/null +++ b/sys/pll/pll_0002.v @@ -0,0 +1,90 @@ +`timescale 1ns/10ps +module pll_0002( + + // interface 'refclk' + input wire refclk, + + // interface 'reset' + input wire rst, + + // interface 'outclk0' + output wire outclk_0, + + // interface 'outclk1' + output wire outclk_1, + + // interface 'locked' + output wire locked +); + + altera_pll #( + .fractional_vco_multiplier("true"), + .reference_clock_frequency("50.0 MHz"), + .operation_mode("direct"), + .number_of_clocks(2), + .output_clock_frequency0("62.668800 MHz"), + .phase_shift0("0 ps"), + .duty_cycle0(50), + .output_clock_frequency1("62.668800 MHz"), + .phase_shift1("-4351 ps"), + .duty_cycle1(50), + .output_clock_frequency2("0 MHz"), + .phase_shift2("0 ps"), + .duty_cycle2(50), + .output_clock_frequency3("0 MHz"), + .phase_shift3("0 ps"), + .duty_cycle3(50), + .output_clock_frequency4("0 MHz"), + .phase_shift4("0 ps"), + .duty_cycle4(50), + .output_clock_frequency5("0 MHz"), + .phase_shift5("0 ps"), + .duty_cycle5(50), + .output_clock_frequency6("0 MHz"), + .phase_shift6("0 ps"), + .duty_cycle6(50), + .output_clock_frequency7("0 MHz"), + .phase_shift7("0 ps"), + .duty_cycle7(50), + .output_clock_frequency8("0 MHz"), + .phase_shift8("0 ps"), + .duty_cycle8(50), + .output_clock_frequency9("0 MHz"), + .phase_shift9("0 ps"), + .duty_cycle9(50), + .output_clock_frequency10("0 MHz"), + .phase_shift10("0 ps"), + .duty_cycle10(50), + .output_clock_frequency11("0 MHz"), + .phase_shift11("0 ps"), + .duty_cycle11(50), + .output_clock_frequency12("0 MHz"), + .phase_shift12("0 ps"), + .duty_cycle12(50), + .output_clock_frequency13("0 MHz"), + .phase_shift13("0 ps"), + .duty_cycle13(50), + .output_clock_frequency14("0 MHz"), + .phase_shift14("0 ps"), + .duty_cycle14(50), + .output_clock_frequency15("0 MHz"), + .phase_shift15("0 ps"), + .duty_cycle15(50), + .output_clock_frequency16("0 MHz"), + .phase_shift16("0 ps"), + .duty_cycle16(50), + .output_clock_frequency17("0 MHz"), + .phase_shift17("0 ps"), + .duty_cycle17(50), + .pll_type("General"), + .pll_subtype("General") + ) altera_pll_i ( + .rst (rst), + .outclk ({outclk_1, outclk_0}), + .locked (locked), + .fboutclk ( ), + .fbclk (1'b0), + .refclk (refclk) + ); +endmodule + diff --git a/sys/pll_hdmi.qip b/sys/pll_hdmi.qip new file mode 100644 index 0000000..2c1e916 --- /dev/null +++ b/sys/pll_hdmi.qip @@ -0,0 +1,337 @@ +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_TOOL_NAME "altera_pll" +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_TOOL_VERSION "17.0" +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_TOOL_ENV "mwpim" +set_global_assignment -library "pll_hdmi" -name MISC_FILE [file join $::quartus(qip_path) "pll_hdmi.cmp"] +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_TARGETED_DEVICE_FAMILY "Cyclone V" +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_GENERATED_DEVICE_FAMILY "{Cyclone V}" +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_QSYS_MODE "UNKNOWN" +set_global_assignment -name SYNTHESIS_ONLY_QIP ON +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_COMPONENT_NAME "cGxsX2hkbWk=" +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_COMPONENT_DISPLAY_NAME "QWx0ZXJhIFBMTA==" +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_COMPONENT_REPORT_HIERARCHY "Off" +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_COMPONENT_INTERNAL "Off" +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_COMPONENT_AUTHOR "QWx0ZXJhIENvcnBvcmF0aW9u" +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_COMPONENT_VERSION "MTcuMA==" +set_global_assignment -entity "pll_hdmi" -library "pll_hdmi" -name IP_COMPONENT_DESCRIPTION "QWx0ZXJhIFBoYXNlLUxvY2tlZCBMb29wIChBTFRFUkFfUExMKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_NAME "cGxsX2hkbWlfMDAwMg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_DISPLAY_NAME "QWx0ZXJhIFBMTA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_REPORT_HIERARCHY "Off" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_INTERNAL "Off" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_AUTHOR "QWx0ZXJhIENvcnBvcmF0aW9u" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_VERSION "MTcuMA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_DESCRIPTION "QWx0ZXJhIFBoYXNlLUxvY2tlZCBMb29wIChBTFRFUkFfUExMKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZGVidWdfcHJpbnRfb3V0cHV0::ZmFsc2U=::ZGVidWdfcHJpbnRfb3V0cHV0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZGVidWdfdXNlX3JiY190YWZfbWV0aG9k::ZmFsc2U=::ZGVidWdfdXNlX3JiY190YWZfbWV0aG9k" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZGV2aWNl::NUNFQkEyRjE3QTc=::ZGV2aWNl" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BsbF9tb2Rl::RnJhY3Rpb25hbC1OIFBMTA==::UExMIE1vZGU=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZnJhY3Rpb25hbF92Y29fbXVsdGlwbGllcg==::dHJ1ZQ==::ZnJhY3Rpb25hbF92Y29fbXVsdGlwbGllcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3JlZmVyZW5jZV9jbG9ja19mcmVxdWVuY3k=::NTAuMA==::UmVmZXJlbmNlIENsb2NrIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cmVmZXJlbmNlX2Nsb2NrX2ZyZXF1ZW5jeQ==::NTAuMCBNSHo=::cmVmZXJlbmNlX2Nsb2NrX2ZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2NoYW5uZWxfc3BhY2luZw==::MC4w::Q2hhbm5lbCBTcGFjaW5n" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX29wZXJhdGlvbl9tb2Rl::ZGlyZWN0::T3BlcmF0aW9uIE1vZGU=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2ZlZWRiYWNrX2Nsb2Nr::R2xvYmFsIENsb2Nr::RmVlZGJhY2sgQ2xvY2s=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2ZyYWN0aW9uYWxfY291dA==::MzI=::RnJhY3Rpb25hbCBjYXJyeSBvdXQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RzbV9vdXRfc2Vs::MXN0X29yZGVy::RFNNIE9yZGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3BlcmF0aW9uX21vZGU=::ZGlyZWN0::b3BlcmF0aW9uX21vZGU=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3VzZV9sb2NrZWQ=::ZmFsc2U=::RW5hYmxlIGxvY2tlZCBvdXRwdXQgcG9ydA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX2Fkdl9wYXJhbXM=::ZmFsc2U=::RW5hYmxlIHBoeXNpY2FsIG91dHB1dCBjbG9jayBwYXJhbWV0ZXJz" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX251bWJlcl9vZl9jbG9ja3M=::MQ==::TnVtYmVyIE9mIENsb2Nrcw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "bnVtYmVyX29mX2Nsb2Nrcw==::MQ==::bnVtYmVyX29mX2Nsb2Nrcw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX211bHRpcGx5X2ZhY3Rvcg==::MQ==::TXVsdGlwbHkgRmFjdG9yIChNLUNvdW50ZXIp" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2ZyYWNfbXVsdGlwbHlfZmFjdG9y::MQ==::RnJhY3Rpb25hbCBNdWx0aXBseSBGYWN0b3IgKEsp" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3Jfbg==::MQ==::RGl2aWRlIEZhY3RvciAoTi1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjA=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kw::NzQuMjU=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzA=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iw::OA==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjA=::MzkwODQyMDE1Mw==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMA==::Ng==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MA==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzA=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDA=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUw::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kx::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Ix::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMQ==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MQ==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMQ==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MQ==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUx::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjI=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3ky::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzI=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iy::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjI=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMg==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Mg==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMg==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Mg==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzI=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDI=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUy::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjM=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kz::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzM=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iz::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjM=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMw==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Mw==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMw==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Mw==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzM=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDM=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUz::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjQ=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k0::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzQ=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I0::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjQ=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNA==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5NA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0NA==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzQ=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDQ=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU0::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjU=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k1::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzU=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I1::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjU=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNQ==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5NQ==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNQ==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0NQ==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzU=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDU=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU1::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjY=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k2::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzY=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I2::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjY=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNg==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Ng==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNg==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Ng==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzY=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDY=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU2::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjc=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k3::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzc=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I3::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3Rvcjc=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yNw==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5Nw==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzNw==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0Nw==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzc=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDc=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU3::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjg=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k4::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzg=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I4::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3Rvcjg=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yOA==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5OA==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzOA==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0OA==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzg=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDg=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU4::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjk=::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3k5::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzk=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3I5::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3Rvcjk=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yOQ==::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5OQ==::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzOQ==::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0OQ==::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzk=::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDk=::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGU5::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEw::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMA==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEw::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMA==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEw::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTA=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTA=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTA=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTA=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEw::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEw::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMA==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEx::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMQ==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEx::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMQ==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEx::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTE=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTE=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTE=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTE=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEx::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEx::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMQ==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEy::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMg==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEy::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMg==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEy::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTI=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTI=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTI=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTI=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEy::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEy::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMg==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjEz::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxMw==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzEz::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxMw==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjEz::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTM=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTM=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTM=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTM=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzEz::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDEz::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxMw==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE0::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNA==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE0::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNA==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE0::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTQ=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTQ=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTQ=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTQ=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE0::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE0::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNA==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE1::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNQ==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE1::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNQ==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE1::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTU=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTU=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTU=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTU=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE1::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE1::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNQ==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE2::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNg==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE2::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNg==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE2::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTY=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTY=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTY=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTY=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE2::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE2::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNg==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Nhc2NhZGVfY291bnRlcjE3::ZmFsc2U=::TWFrZSB0aGlzIGEgY2FzY2FkZSBjb3VudGVy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX291dHB1dF9jbG9ja19mcmVxdWVuY3kxNw==::MTAwLjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE3::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3IxNw==::MQ==::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE3::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMTc=::MQ==::QWN0dWFsIERpdmlkZSBGYWN0b3I=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9vdXRwdXRfY2xvY2tfZnJlcXVlbmN5MTc=::MCBNSHo=::QWN0dWFsIEZyZXF1ZW5jeQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BzX3VuaXRzMTc=::cHM=::UGhhc2UgU2hpZnQgdW5pdHM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0MTc=::MA==::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BoYXNlX3NoaWZ0X2RlZzE3::MC4w::UGhhc2UgU2hpZnQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9waGFzZV9zaGlmdDE3::MA==::QWN0dWFsIFBoYXNlIFNoaWZ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2R1dHlfY3ljbGUxNw==::NTA=::RHV0eSBDeWNsZQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTA=::NzQuMjUwMDAwIE1Ieg==::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTA=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQw::MCBwcw==::cGhhc2Vfc2hpZnQw" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTA=::NTA=::ZHV0eV9jeWNsZTA=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQx::MCBwcw==::cGhhc2Vfc2hpZnQx" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE=::NTA=::ZHV0eV9jeWNsZTE=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTI=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTI=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQy::MCBwcw==::cGhhc2Vfc2hpZnQy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTI=::NTA=::ZHV0eV9jeWNsZTI=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTM=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQz::MCBwcw==::cGhhc2Vfc2hpZnQz" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTM=::NTA=::ZHV0eV9jeWNsZTM=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTQ=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ0::MCBwcw==::cGhhc2Vfc2hpZnQ0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTQ=::NTA=::ZHV0eV9jeWNsZTQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTU=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTU=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ1::MCBwcw==::cGhhc2Vfc2hpZnQ1" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTU=::NTA=::ZHV0eV9jeWNsZTU=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTY=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTY=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ2::MCBwcw==::cGhhc2Vfc2hpZnQ2" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTY=::NTA=::ZHV0eV9jeWNsZTY=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTc=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTc=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ3::MCBwcw==::cGhhc2Vfc2hpZnQ3" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTc=::NTA=::ZHV0eV9jeWNsZTc=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTg=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTg=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ4::MCBwcw==::cGhhc2Vfc2hpZnQ4" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTg=::NTA=::ZHV0eV9jeWNsZTg=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTk=::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTk=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQ5::MCBwcw==::cGhhc2Vfc2hpZnQ5" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTk=::NTA=::ZHV0eV9jeWNsZTk=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEw::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEw" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMA==::MCBwcw==::cGhhc2Vfc2hpZnQxMA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEw::NTA=::ZHV0eV9jeWNsZTEw" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEx::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEx" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMQ==::MCBwcw==::cGhhc2Vfc2hpZnQxMQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEx::NTA=::ZHV0eV9jeWNsZTEx" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEy::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMg==::MCBwcw==::cGhhc2Vfc2hpZnQxMg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEy::NTA=::ZHV0eV9jeWNsZTEy" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEz::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTEz" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxMw==::MCBwcw==::cGhhc2Vfc2hpZnQxMw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTEz::NTA=::ZHV0eV9jeWNsZTEz" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE0::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNA==::MCBwcw==::cGhhc2Vfc2hpZnQxNA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE0::NTA=::ZHV0eV9jeWNsZTE0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE1::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE1" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNQ==::MCBwcw==::cGhhc2Vfc2hpZnQxNQ==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE1::NTA=::ZHV0eV9jeWNsZTE1" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE2::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE2" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNg==::MCBwcw==::cGhhc2Vfc2hpZnQxNg==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE2::NTA=::ZHV0eV9jeWNsZTE2" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE3::MCBNSHo=::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE3" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQxNw==::MCBwcw==::cGhhc2Vfc2hpZnQxNw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "ZHV0eV9jeWNsZTE3::NTA=::ZHV0eV9jeWNsZTE3" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BsbF9hdXRvX3Jlc2V0::T24=::UExMIEF1dG8gUmVzZXQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BsbF9iYW5kd2lkdGhfcHJlc2V0::QXV0bw==::UExMIEJhbmR3aWR0aCBQcmVzZXQ=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX3JlY29uZg==::ZmFsc2U=::RW5hYmxlIGR5bmFtaWMgcmVjb25maWd1cmF0aW9uIG9mIFBMTA==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX2Rwc19wb3J0cw==::ZmFsc2U=::RW5hYmxlIGFjY2VzcyB0byBkeW5hbWljIHBoYXNlIHNoaWZ0IHBvcnRz" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2VuX3Bob3V0X3BvcnRz::ZmFsc2U=::RW5hYmxlIGFjY2VzcyB0byBQTEwgRFBBIG91dHB1dCBwb3J0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGxsX3R5cGU=::R2VuZXJhbA==::UExMIFRZUEU=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "cGxsX3N1YnR5cGU=::R2VuZXJhbA==::UExMIFNVQlRZUEU=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BhcmFtZXRlcl9saXN0::TS1Db3VudGVyIEhpIERpdmlkZSxNLUNvdW50ZXIgTG93IERpdmlkZSxOLUNvdW50ZXIgSGkgRGl2aWRlLE4tQ291bnRlciBMb3cgRGl2aWRlLE0tQ291bnRlciBCeXBhc3MgRW5hYmxlLE4tQ291bnRlciBCeXBhc3MgRW5hYmxlLE0tQ291bnRlciBPZGQgRGl2aWRlIEVuYWJsZSxOLUNvdW50ZXIgT2RkIERpdmlkZSBFbmFibGUsQy1Db3VudGVyLTAgSGkgRGl2aWRlLEMtQ291bnRlci0wIExvdyBEaXZpZGUsQy1Db3VudGVyLTAgQ29hcnNlIFBoYXNlIFNoaWZ0LEMtQ291bnRlci0wIFZDTyBQaGFzZSBUYXAsQy1Db3VudGVyLTAgSW5wdXQgU291cmNlLEMtQ291bnRlci0wIEJ5cGFzcyBFbmFibGUsQy1Db3VudGVyLTAgT2RkIERpdmlkZSBFbmFibGUsVkNPIFBvc3QgRGl2aWRlIENvdW50ZXIgRW5hYmxlLENoYXJnZSBQdW1wIGN1cnJlbnQgKHVBKSxMb29wIEZpbHRlciBCYW5kd2lkdGggUmVzaXN0b3IgKE9obXMpICxQTEwgT3V0cHV0IFZDTyBGcmVxdWVuY3ksSy1GcmFjdGlvbmFsIERpdmlzaW9uIFZhbHVlIChEU00pLEZlZWRiYWNrIENsb2NrIFR5cGUsRmVlZGJhY2sgQ2xvY2sgTVVYIDEsRmVlZGJhY2sgQ2xvY2sgTVVYIDIsTSBDb3VudGVyIFNvdXJjZSBNVVgsUExMIEF1dG8gUmVzZXQ=::UGFyYW1ldGVyIE5hbWVz" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3BhcmFtZXRlcl92YWx1ZXM=::NCw0LDI1NiwyNTYsZmFsc2UsdHJ1ZSxmYWxzZSxmYWxzZSwzLDMsMSwwLHBoX211eF9jbGssZmFsc2UsZmFsc2UsMiwyMCw0MDAwLDQ0NS40OTk5OTkgTUh6LDM5MDg0MjAxNTMsbm9uZSxnbGIsbV9jbnQscGhfbXV4X2Nsayx0cnVl::UGFyYW1ldGVyIFZhbHVlcw==" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX21pZl9nZW5lcmF0ZQ==::ZmFsc2U=::R2VuZXJhdGUgTUlGIGZpbGU=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9taWZfZHBz::ZmFsc2U=::RW5hYmxlIER5bmFtaWMgUGhhc2UgU2hpZnQgZm9yIE1JRiBzdHJlYW1pbmc=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Rwc19jbnRy::QzA=::RFBTIENvdW50ZXIgU2VsZWN0aW9u" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Rwc19udW0=::MQ==::TnVtYmVyIG9mIER5bmFtaWMgUGhhc2UgU2hpZnRz" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2Rwc19kaXI=::UG9zaXRpdmU=::RHluYW1pYyBQaGFzZSBTaGlmdCBEaXJlY3Rpb24=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX3JlZmNsa19zd2l0Y2g=::ZmFsc2U=::Q3JlYXRlIGEgc2Vjb25kIGlucHV0IGNsayAncmVmY2xrMSc=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9jYXNjYWRlX291dA==::ZmFsc2U=::Q3JlYXRlIGEgJ2Nhc2NhZGVfb3V0JyBzaWduYWwgdG8gY29ubmVjdCB3aXRoIGEgZG93bnN0cmVhbSBQTEw=" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_COMPONENT_PARAMETER "Z3VpX2VuYWJsZV9jYXNjYWRlX2lu::ZmFsc2U=::Q3JlYXRlIGFuIGFkanBsbGluIG9yIGNjbGsgc2lnbmFsIHRvIGNvbm5lY3Qgd2l0aCBhbiB1cHN0cmVhbSBQTEw=" + +set_global_assignment -library "pll_hdmi" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_hdmi.v"] +set_global_assignment -library "pll_hdmi" -name VERILOG_FILE [file join $::quartus(qip_path) "pll_hdmi/pll_hdmi_0002.v"] +set_global_assignment -library "pll_hdmi" -name QIP_FILE [file join $::quartus(qip_path) "pll_hdmi/pll_hdmi_0002.qip"] + +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_TOOL_NAME "altera_pll" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_TOOL_VERSION "17.0" +set_global_assignment -entity "pll_hdmi_0002" -library "pll_hdmi" -name IP_TOOL_ENV "mwpim" diff --git a/sys/pll_hdmi.v b/sys/pll_hdmi.v new file mode 100644 index 0000000..5ff1175 --- /dev/null +++ b/sys/pll_hdmi.v @@ -0,0 +1,252 @@ +// megafunction wizard: %Altera PLL v17.0% +// GENERATION: XML +// pll_hdmi.v + +// Generated using ACDS version 17.0 598 + +`timescale 1 ps / 1 ps +module pll_hdmi ( + input wire refclk, // refclk.clk + input wire rst, // reset.reset + output wire outclk_0 // outclk0.clk + ); + + pll_hdmi_0002 pll_hdmi_inst ( + .refclk (refclk), // refclk.clk + .rst (rst), // reset.reset + .outclk_0 (outclk_0), // outclk0.clk + .locked () // (terminated) + ); + +endmodule +// Retrieval info: +// +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// Retrieval info: +// IPFS_FILES : pll_hdmi.vo +// RELATED_FILES: pll_hdmi.v, pll_hdmi_0002.v diff --git a/sys/pll_hdmi/pll_hdmi_0002.qip b/sys/pll_hdmi/pll_hdmi_0002.qip new file mode 100644 index 0000000..fb8053d --- /dev/null +++ b/sys/pll_hdmi/pll_hdmi_0002.qip @@ -0,0 +1,4 @@ +set_instance_assignment -name PLL_COMPENSATION_MODE DIRECT -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_CHANNEL_SPACING "0.0 KHz" -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_AUTO_RESET ON -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" +set_instance_assignment -name PLL_BANDWIDTH_PRESET AUTO -to "*pll_hdmi_0002*|altera_pll:altera_pll_i*|*" diff --git a/sys/pll_hdmi/pll_hdmi_0002.v b/sys/pll_hdmi/pll_hdmi_0002.v new file mode 100644 index 0000000..6bea229 --- /dev/null +++ b/sys/pll_hdmi/pll_hdmi_0002.v @@ -0,0 +1,87 @@ +`timescale 1ns/10ps +module pll_hdmi_0002( + + // interface 'refclk' + input wire refclk, + + // interface 'reset' + input wire rst, + + // interface 'outclk0' + output wire outclk_0, + + // interface 'locked' + output wire locked +); + + altera_pll #( + .fractional_vco_multiplier("true"), + .reference_clock_frequency("50.0 MHz"), + .operation_mode("direct"), + .number_of_clocks(1), + .output_clock_frequency0("74.250000 MHz"), + .phase_shift0("0 ps"), + .duty_cycle0(50), + .output_clock_frequency1("0 MHz"), + .phase_shift1("0 ps"), + .duty_cycle1(50), + .output_clock_frequency2("0 MHz"), + .phase_shift2("0 ps"), + .duty_cycle2(50), + .output_clock_frequency3("0 MHz"), + .phase_shift3("0 ps"), + .duty_cycle3(50), + .output_clock_frequency4("0 MHz"), + .phase_shift4("0 ps"), + .duty_cycle4(50), + .output_clock_frequency5("0 MHz"), + .phase_shift5("0 ps"), + .duty_cycle5(50), + .output_clock_frequency6("0 MHz"), + .phase_shift6("0 ps"), + .duty_cycle6(50), + .output_clock_frequency7("0 MHz"), + .phase_shift7("0 ps"), + .duty_cycle7(50), + .output_clock_frequency8("0 MHz"), + .phase_shift8("0 ps"), + .duty_cycle8(50), + .output_clock_frequency9("0 MHz"), + .phase_shift9("0 ps"), + .duty_cycle9(50), + .output_clock_frequency10("0 MHz"), + .phase_shift10("0 ps"), + .duty_cycle10(50), + .output_clock_frequency11("0 MHz"), + .phase_shift11("0 ps"), + .duty_cycle11(50), + .output_clock_frequency12("0 MHz"), + .phase_shift12("0 ps"), + .duty_cycle12(50), + .output_clock_frequency13("0 MHz"), + .phase_shift13("0 ps"), + .duty_cycle13(50), + .output_clock_frequency14("0 MHz"), + .phase_shift14("0 ps"), + .duty_cycle14(50), + .output_clock_frequency15("0 MHz"), + .phase_shift15("0 ps"), + .duty_cycle15(50), + .output_clock_frequency16("0 MHz"), + .phase_shift16("0 ps"), + .duty_cycle16(50), + .output_clock_frequency17("0 MHz"), + .phase_shift17("0 ps"), + .duty_cycle17(50), + .pll_type("General"), + .pll_subtype("General") + ) altera_pll_i ( + .rst (rst), + .outclk ({outclk_0}), + .locked (locked), + .fboutclk ( ), + .fbclk (1'b0), + .refclk (refclk) + ); +endmodule + diff --git a/sys/scandoubler.v b/sys/scandoubler.v new file mode 100644 index 0000000..f0728fc --- /dev/null +++ b/sys/scandoubler.v @@ -0,0 +1,186 @@ +// +// scandoubler.v +// +// Copyright (c) 2015 Till Harbaum +// Copyright (c) 2017 Sorgelig +// +// This source file 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 3 of the License, or +// (at your option) any later version. +// +// This source file 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, see . + +// TODO: Delay vsync one line + +module scandoubler #(parameter LENGTH, parameter HALF_DEPTH) +( + // system interface + input clk_sys, + input ce_pix, + output ce_pix_out, + + input hq2x, + + // shifter video interface + input hs_in, + input vs_in, + input hb_in, + input vb_in, + + input [DWIDTH:0] r_in, + input [DWIDTH:0] g_in, + input [DWIDTH:0] b_in, + input mono, + + // output interface + output reg hs_out, + output vs_out, + output hb_out, + output vb_out, + output [DWIDTH:0] r_out, + output [DWIDTH:0] g_out, + output [DWIDTH:0] b_out +); + + +localparam DWIDTH = HALF_DEPTH ? 3 : 7; + +assign vs_out = vs_in; +assign ce_pix_out = ce_x4; + +//Compensate picture shift after HQ2x +assign vb_out = vbo[2]; +assign hb_out = &hbo[5:4]; + +reg [7:0] pix_len = 0; +wire [7:0] pl = pix_len + 1'b1; + +reg ce_x1, ce_x4; +reg req_line_reset; +always @(negedge clk_sys) begin + reg old_ce; + reg [2:0] ce_cnt; + + reg [7:0] pixsz2, pixsz4 = 0; + + old_ce <= ce_pix; + if(~&pix_len) pix_len <= pix_len + 1'd1; + + ce_x4 <= 0; + ce_x1 <= 0; + + // use such odd comparison to place ce_x4 evenly if master clock isn't multiple 4. + if((pl == pixsz4) || (pl == pixsz2) || (pl == (pixsz2+pixsz4))) begin + ce_x4 <= 1; + end + + if(~old_ce & ce_pix) begin + pixsz2 <= {1'b0, pl[7:1]}; + pixsz4 <= {2'b00, pl[7:2]}; + ce_x1 <= 1; + ce_x4 <= 1; + pix_len <= 0; + req_line_reset <= 0; + + if(hb_in) req_line_reset <= 1; + end +end + +localparam AWIDTH = `BITS_TO_FIT(LENGTH); +Hq2x #(.LENGTH(LENGTH), .HALF_DEPTH(HALF_DEPTH)) Hq2x +( + .clk(clk_sys), + .ce_x4(ce_x4), + .inputpixel({b_d,g_d,r_d}), + .mono(mono), + .disable_hq2x(~hq2x), + .reset_frame(vs_in), + .reset_line(req_line_reset), + .read_y(sd_line), + .read_x(sd_h), + .outpixel({b_out,g_out,r_out}) +); + +reg [10:0] sd_h; +reg [1:0] sd_line; +reg [2:0] vbo; +reg [5:0] hbo; + +reg [DWIDTH:0] r_d; +reg [DWIDTH:0] g_d; +reg [DWIDTH:0] b_d; + + +always @(posedge clk_sys) begin + + reg [11:0] hs_max,hs_rise; + reg [10:0] hcnt; + reg [11:0] sd_hcnt; + reg [11:0] hde_start, hde_end; + + reg hs, hs2, vs, hb; + + if(ce_x1) begin + hs <= hs_in; + hb <= hb_in; + + r_d <= r_in; + g_d <= g_in; + b_d <= b_in; + + if(hb && !hb_in) begin + hde_start <= {hcnt,1'b0}; + vbo <= {vbo[1:0], vb_in}; + end + if(!hb && hb_in) hde_end <= {hcnt,1'b0}; + + // falling edge of hsync indicates start of line + if(hs && !hs_in) begin + hs_max <= {hcnt,1'b1}; + hcnt <= 0; + end else begin + hcnt <= hcnt + 1'd1; + end + + // save position of rising edge + if(!hs && hs_in) hs_rise <= {hcnt,1'b1}; + + vs <= vs_in; + if(vs && ~vs_in) sd_line <= 0; + end + + if(ce_x4) begin + hs2 <= hs_in; + hbo[5:1] <= hbo[4:0]; + + // output counter synchronous to input and at twice the rate + sd_hcnt <= sd_hcnt + 1'd1; + if(~&hbo) sd_h <= sd_h + 1'd1; + + if(hs2 && !hs_in) sd_hcnt <= hs_max; + if(sd_hcnt == hs_max) sd_hcnt <= 0; + + + //prepare to read in advance + if(sd_hcnt == (hde_start-2)) begin + sd_h <= 0; + sd_line <= sd_line + 1'd1; + end + + if(sd_hcnt == hde_start) hbo[0] <= 0; + if(sd_hcnt == hde_end) hbo[0] <= 1; + + // replicate horizontal sync at twice the speed + if(sd_hcnt == hs_max) hs_out <= 0; + if(sd_hcnt == hs_rise) hs_out <= 1; + end +end + +endmodule diff --git a/sys/sdram.sv b/sys/sdram.sv new file mode 100644 index 0000000..de8e425 --- /dev/null +++ b/sys/sdram.sv @@ -0,0 +1,194 @@ +// +// +// sdram controller implementation for the MiST/MiSTer boards +// +// Copyright (c) 2015 Till Harbaum +// Copyright (c) 2017 Sorgelig +// +// This source file 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 3 of the License, or +// (at your option) any later version. +// +// This source file 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, see . +// + +// +// +// This SDRAM module provides/writes the data in 8 cycles of clock. +// So, with 64MHz of system clock, it can emulate 8MHz asynchronous DRAM. +// +// + +module sdram +( + + // interface to the MT48LC16M16 chip + inout [15:0] sd_data, // 16 bit bidirectional data bus + output reg [12:0] sd_addr, // 13 bit multiplexed address bus + output reg [1:0] sd_dqm, // two byte masks + output reg [1:0] sd_ba, // two banks + output sd_cs, // a single chip select + output sd_we, // write enable + output sd_ras, // row address select + output sd_cas, // columns address select + + // cpu/chipset interface + input init, // init signal after FPGA config to initialize RAM + input clk, // sdram is accessed at 64MHz + input sync, + + input [15:0] din, // data input from chipset/cpu + output reg [15:0] dout, // data output to chipset/cpu + input [23:0] addr, // 24 bit word address + input [1:0] ds, // upper/lower data strobe + input oe, // cpu/chipset requests read + input we // cpu/chipset requests write +); + +localparam RASCAS_DELAY = 3'd2; // tRCD=20ns -> 3 cycles@128MHz +localparam BURST_LENGTH = 3'b000; // 000=1, 001=2, 010=4, 011=8 +localparam ACCESS_TYPE = 1'b0; // 0=sequential, 1=interleaved +localparam CAS_LATENCY = 3'd2; // 2/3 allowed +localparam OP_MODE = 2'b00; // only 00 (standard operation) allowed +localparam NO_WRITE_BURST = 1'b1; // 0= write burst enabled, 1=only single access write + +localparam MODE = { 3'b000, NO_WRITE_BURST, OP_MODE, CAS_LATENCY, ACCESS_TYPE, BURST_LENGTH}; + + +// --------------------------------------------------------------------- +// ------------------------ cycle state machine ------------------------ +// --------------------------------------------------------------------- + +// The state machine runs at 128Mhz synchronous to the 8 Mhz chipset clock. +// It wraps from T15 to T0 on the rising edge of clk_8 + +localparam STATE_FIRST = 3'd0; // first state in cycle +localparam STATE_CMD_START = 3'd1; // state in which a new command can be started +localparam STATE_CMD_CONT = STATE_CMD_START + RASCAS_DELAY; // command can be continued +localparam STATE_READ = STATE_CMD_CONT + CAS_LATENCY + 4'd1; +localparam STATE_HIGHZ = STATE_READ - 4'd1; // disable output to prevent contention + + +// --------------------------------------------------------------------- +// --------------------------- startup/reset --------------------------- +// --------------------------------------------------------------------- + +// wait 1ms (32 8Mhz cycles) after FPGA config is done before going +// into normal operation. Initialize the ram in the last 16 reset cycles (cycles 15-0) +reg [4:0] reset; +always @(posedge clk) begin + if(init) reset <= 5'h1f; + else if((stage == STATE_FIRST) && (reset != 0)) + reset <= reset - 5'd1; +end + +// --------------------------------------------------------------------- +// ------------------ generate ram control signals --------------------- +// --------------------------------------------------------------------- + +// all possible commands +localparam CMD_INHIBIT = 4'b1111; +localparam CMD_NOP = 4'b0111; +localparam CMD_ACTIVE = 4'b0011; +localparam CMD_READ = 4'b0101; +localparam CMD_WRITE = 4'b0100; +localparam CMD_BURST_TERMINATE = 4'b0110; +localparam CMD_PRECHARGE = 4'b0010; +localparam CMD_AUTO_REFRESH = 4'b0001; +localparam CMD_LOAD_MODE = 4'b0000; + +reg [3:0] sd_cmd; // current command sent to sd ram + +// drive control signals according to current command +assign sd_cs = sd_cmd[3]; +assign sd_ras = sd_cmd[2]; +assign sd_cas = sd_cmd[1]; +assign sd_we = sd_cmd[0]; + +// drive ram data lines when writing, set them as inputs otherwise +assign sd_data = mode[1] ? din_r : 16'bZZZZZZZZZZZZZZZZ; + +reg [1:0] mode; +reg [15:0] din_r; +reg [2:0] stage; + +always @(posedge clk) begin + reg [12:0] addr_r; + reg [1:0] ds_r; + reg old_sync; + + if(|stage) stage <= stage + 1'd1; + + old_sync <= sync; + if(~old_sync & sync) stage <= 1; + + sd_cmd <= CMD_INHIBIT; // default: idle + + if(reset != 0) begin + // initialization takes place at the end of the reset phase + if(stage == STATE_CMD_START) begin + + if(reset == 13) begin + sd_cmd <= CMD_PRECHARGE; + sd_addr[10] <= 1'b1; // precharge all banks + end + + if(reset == 2) begin + sd_cmd <= CMD_LOAD_MODE; + sd_addr <= MODE; + end + + end + mode <= 0; + sd_dqm <= 2'b11; + end else begin + + // normal operation + if(stage == STATE_CMD_START) begin + if(we || oe) begin + + mode <= {we, oe}; + + // RAS phase + sd_cmd <= CMD_ACTIVE; + sd_addr <= { 1'b0, addr[19:8] }; + sd_ba <= addr[21:20]; + + ds_r <= ds; + din_r <= din; + addr_r <= { 4'b0010, addr[22], addr[7:0] }; // auto precharge + end + else begin + sd_cmd <= CMD_AUTO_REFRESH; + mode <= 0; + end + end + + // CAS phase + if(stage == STATE_CMD_CONT && mode) begin + sd_cmd <= mode[1] ? CMD_WRITE : CMD_READ; + sd_addr <= addr_r; + + if(mode[1]) sd_dqm <= ~ds_r; + else sd_dqm <= 2'b00; + end + + if(stage == STATE_HIGHZ) begin + sd_dqm <= 2'b11; // disable chip output + mode[1] <= 0; // disable data output + end + + if(stage == STATE_READ && mode) begin + dout <= sd_data; + end + end +end + +endmodule diff --git a/sys/sigma_delta_dac.v b/sys/sigma_delta_dac.v new file mode 100644 index 0000000..d0d6be0 --- /dev/null +++ b/sys/sigma_delta_dac.v @@ -0,0 +1,33 @@ +// +// PWM DAC +// +// MSBI is the highest bit number. NOT amount of bits! +// +module sigma_delta_dac #(parameter MSBI=7, parameter INV=1'b1) +( + output reg DACout, //Average Output feeding analog lowpass + input [MSBI:0] DACin, //DAC input (excess 2**MSBI) + input CLK, + input RESET +); + +reg [MSBI+2:0] DeltaAdder; //Output of Delta Adder +reg [MSBI+2:0] SigmaAdder; //Output of Sigma Adder +reg [MSBI+2:0] SigmaLatch; //Latches output of Sigma Adder +reg [MSBI+2:0] DeltaB; //B input of Delta Adder + +always @(*) DeltaB = {SigmaLatch[MSBI+2], SigmaLatch[MSBI+2]} << (MSBI+1); +always @(*) DeltaAdder = DACin + DeltaB; +always @(*) SigmaAdder = DeltaAdder + SigmaLatch; + +always @(posedge CLK or posedge RESET) begin + if(RESET) begin + SigmaLatch <= 1'b1 << (MSBI+1); + DACout <= INV; + end else begin + SigmaLatch <= SigmaAdder; + DACout <= SigmaLatch[MSBI+2] ^ INV; + end +end + +endmodule diff --git a/sys/spdif.v b/sys/spdif.v new file mode 100644 index 0000000..d4e711e --- /dev/null +++ b/sys/spdif.v @@ -0,0 +1,392 @@ +//----------------------------------------------------------------- +// SPDIF Transmitter +// V0.1 +// Ultra-Embedded.com +// Copyright 2012 +// +// Email: admin@ultra-embedded.com +// +// License: GPL +// If you would like a version with a more permissive license for +// use in closed source commercial applications please contact me +// for details. +//----------------------------------------------------------------- +// +// This file is open source HDL; 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 file 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 file; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +//----------------------------------------------------------------- +// altera message_off 10762 +// altera message_off 10240 + +module spdif + +//----------------------------------------------------------------- +// Params +//----------------------------------------------------------------- +#( + parameter CLK_RATE = 50000000, + parameter AUDIO_RATE = 48000, + + // Generated params + parameter WHOLE_CYCLES = (CLK_RATE) / (AUDIO_RATE*128), + parameter ERROR_BASE = 10000, + parameter [63:0] ERRORS_PER_BIT = ((CLK_RATE * ERROR_BASE) / (AUDIO_RATE*128)) - (WHOLE_CYCLES * ERROR_BASE) +) + +//----------------------------------------------------------------- +// Ports +//----------------------------------------------------------------- +( + input clk_i, + input rst_i, + input half_rate, + + // Output + output spdif_o, + + // Audio interface (16-bit x 2 = RL) + input [15:0] audio_r, + input [15:0] audio_l, + output sample_req_o +); + +reg bit_clk_q; + +// Clock pulse generator +always @ (posedge rst_i or posedge clk_i) begin + reg [31:0] count_q; + reg [31:0] error_q; + reg ce; + + if (rst_i) begin + count_q <= 0; + error_q <= 0; + bit_clk_q <= 1; + ce <= 0; + end + else + begin + if(count_q == WHOLE_CYCLES-1) begin + if (error_q < (ERROR_BASE - ERRORS_PER_BIT)) begin + error_q <= error_q + ERRORS_PER_BIT[31:0]; + count_q <= 0; + end else begin + error_q <= error_q + ERRORS_PER_BIT[31:0] - ERROR_BASE; + count_q <= count_q + 1; + end + end else if(count_q == WHOLE_CYCLES) begin + count_q <= 0; + end else begin + count_q <= count_q + 1; + end + + bit_clk_q <= 0; + if(!count_q) begin + ce <= ~ce; + if(~half_rate || ce) bit_clk_q <= 1; + end + end +end + +//----------------------------------------------------------------- +// Core SPDIF +//----------------------------------------------------------------- + +wire [31:0] sample_i = {audio_r, audio_l}; + +spdif_core +u_core +( + .clk_i(clk_i), + .rst_i(rst_i), + + .bit_out_en_i(bit_clk_q), + + .spdif_o(spdif_o), + + .sample_i(sample_i), + .sample_req_o(sample_req_o) +); + +endmodule + +module spdif_core +( + input clk_i, + input rst_i, + + // SPDIF bit output enable + // Single cycle pulse synchronous to clk_i which drives + // the output bit rate. + // For 44.1KHz, 44100×32×2×2 = 5,644,800Hz + // For 48KHz, 48000×32×2×2 = 6,144,000Hz + input bit_out_en_i, + + // Output + output spdif_o, + + // Audio interface (16-bit x 2 = RL) + input [31:0] sample_i, + output reg sample_req_o +); + +//----------------------------------------------------------------- +// Registers +//----------------------------------------------------------------- +reg [15:0] audio_sample_q; +reg [8:0] subframe_count_q; + +reg load_subframe_q; +reg [7:0] preamble_q; +wire [31:0] subframe_w; + +reg [5:0] bit_count_q; +reg bit_toggle_q; + +reg spdif_out_q; + +reg [5:0] parity_count_q; + +//----------------------------------------------------------------- +// Subframe Counter +//----------------------------------------------------------------- +always @ (posedge rst_i or posedge clk_i ) +begin + if (rst_i == 1'b1) + subframe_count_q <= 9'd0; + else if (load_subframe_q) + begin + // 192 frames (384 subframes) in an audio block + if (subframe_count_q == 9'd383) + subframe_count_q <= 9'd0; + else + subframe_count_q <= subframe_count_q + 9'd1; + end +end + +//----------------------------------------------------------------- +// Sample capture +//----------------------------------------------------------------- +reg [15:0] sample_buf_q; + +always @ (posedge rst_i or posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + audio_sample_q <= 16'h0000; + sample_buf_q <= 16'h0000; + sample_req_o <= 1'b0; + end + else if (load_subframe_q) + begin + // Start of frame (first subframe)? + if (subframe_count_q[0] == 1'b0) + begin + // Use left sample + audio_sample_q <= sample_i[15:0]; + + // Store right sample + sample_buf_q <= sample_i[31:16]; + + // Request next sample + sample_req_o <= 1'b1; + end + else + begin + // Use right sample + audio_sample_q <= sample_buf_q; + + sample_req_o <= 1'b0; + end + end + else + sample_req_o <= 1'b0; +end + +// Timeslots 3 - 0 = Preamble +assign subframe_w[3:0] = 4'b0000; + +// Timeslots 7 - 4 = 24-bit audio LSB +assign subframe_w[7:4] = 4'b0000; + +// Timeslots 11 - 8 = 20-bit audio LSB +assign subframe_w[11:8] = 4'b0000; + +// Timeslots 27 - 12 = 16-bit audio +assign subframe_w[27:12] = audio_sample_q; + +// Timeslots 28 = Validity +assign subframe_w[28] = 1'b0; // Valid + +// Timeslots 29 = User bit +assign subframe_w[29] = 1'b0; + +// Timeslots 30 = Channel status bit +assign subframe_w[30] = 1'b0; + +// Timeslots 31 = Even Parity bit (31:4) +assign subframe_w[31] = 1'b0; + +//----------------------------------------------------------------- +// Preamble +//----------------------------------------------------------------- +localparam PREAMBLE_Z = 8'b00010111; +localparam PREAMBLE_Y = 8'b00100111; +localparam PREAMBLE_X = 8'b01000111; + +reg [7:0] preamble_r; + +always @ * +begin + // Start of audio block? + // Z(B) - Left channel + if (subframe_count_q == 9'd0) + preamble_r = PREAMBLE_Z; // Z(B) + // Right Channel? + else if (subframe_count_q[0] == 1'b1) + preamble_r = PREAMBLE_Y; // Y(W) + // Left Channel (but not start of block)? + else + preamble_r = PREAMBLE_X; // X(M) +end + +always @ (posedge rst_i or posedge clk_i ) +if (rst_i == 1'b1) + preamble_q <= 8'h00; +else if (load_subframe_q) + preamble_q <= preamble_r; + +//----------------------------------------------------------------- +// Parity Counter +//----------------------------------------------------------------- +always @ (posedge rst_i or posedge clk_i ) +begin + if (rst_i == 1'b1) + begin + parity_count_q <= 6'd0; + end + // Time to output a bit? + else if (bit_out_en_i) + begin + // Preamble bits? + if (bit_count_q < 6'd8) + begin + parity_count_q <= 6'd0; + end + // Normal timeslots + else if (bit_count_q < 6'd62) + begin + // On first pass through this timeslot, count number of high bits + if (bit_count_q[0] == 0 && subframe_w[bit_count_q / 2] == 1'b1) + parity_count_q <= parity_count_q + 6'd1; + end + end +end + +//----------------------------------------------------------------- +// Bit Counter +//----------------------------------------------------------------- +always @ (posedge rst_i or posedge clk_i) +begin + if (rst_i == 1'b1) + begin + bit_count_q <= 6'b0; + load_subframe_q <= 1'b1; + end + // Time to output a bit? + else if (bit_out_en_i) + begin + // 32 timeslots (x2 for double frequency) + if (bit_count_q == 6'd63) + begin + bit_count_q <= 6'd0; + load_subframe_q <= 1'b1; + end + else + begin + bit_count_q <= bit_count_q + 6'd1; + load_subframe_q <= 1'b0; + end + end + else + load_subframe_q <= 1'b0; +end + +//----------------------------------------------------------------- +// Bit half toggle +//----------------------------------------------------------------- +always @ (posedge rst_i or posedge clk_i) +if (rst_i == 1'b1) + bit_toggle_q <= 1'b0; +// Time to output a bit? +else if (bit_out_en_i) + bit_toggle_q <= ~bit_toggle_q; + +//----------------------------------------------------------------- +// Output bit (BMC encoded) +//----------------------------------------------------------------- +reg bit_r; + +always @ * +begin + bit_r = spdif_out_q; + + // Time to output a bit? + if (bit_out_en_i) + begin + // Preamble bits? + if (bit_count_q < 6'd8) + begin + bit_r = preamble_q[bit_count_q[2:0]]; + end + // Normal timeslots + else if (bit_count_q < 6'd62) + begin + if (subframe_w[bit_count_q / 2] == 1'b0) + begin + if (bit_toggle_q == 1'b0) + bit_r = ~spdif_out_q; + else + bit_r = spdif_out_q; + end + else + bit_r = ~spdif_out_q; + end + // Parity timeslot + else + begin + // Even number of high bits, make odd + if (parity_count_q[0] == 1'b0) + begin + if (bit_toggle_q == 1'b0) + bit_r = ~spdif_out_q; + else + bit_r = spdif_out_q; + end + else + bit_r = ~spdif_out_q; + end + end +end + +always @ (posedge rst_i or posedge clk_i ) +if (rst_i == 1'b1) + spdif_out_q <= 1'b0; +else + spdif_out_q <= bit_r; + +assign spdif_o = spdif_out_q; + +endmodule diff --git a/sys/sync_vg.v b/sys/sync_vg.v new file mode 100644 index 0000000..c54ba2f --- /dev/null +++ b/sys/sync_vg.v @@ -0,0 +1,123 @@ +module sync_vg +#( + parameter X_BITS=12, + Y_BITS=12 +) +( + input wire clk, + input wire reset, + input wire interlaced, + input wire [Y_BITS-1:0] v_total_0, + input wire [Y_BITS-1:0] v_fp_0, + input wire [Y_BITS-1:0] v_bp_0, + input wire [Y_BITS-1:0] v_sync_0, + input wire [Y_BITS-1:0] v_total_1, + input wire [Y_BITS-1:0] v_fp_1, + input wire [Y_BITS-1:0] v_bp_1, + input wire [Y_BITS-1:0] v_sync_1, + input wire [X_BITS-1:0] h_total, + input wire [X_BITS-1:0] h_fp, + input wire [X_BITS-1:0] h_bp, + input wire [X_BITS-1:0] h_sync, + input wire [X_BITS-1:0] hv_offset_0, + input wire [X_BITS-1:0] hv_offset_1, + output reg vs_out, + output reg hs_out, + output reg hde_out, + output reg vde_out, + output reg [Y_BITS:0] v_count_out, + output reg [X_BITS-1:0] h_count_out, + output reg [X_BITS-1:0] x_out, + output reg [Y_BITS:0] y_out, + output reg field_out, + output wire clk_out +); + +reg [X_BITS-1:0] h_count; +reg [Y_BITS-1:0] v_count; +reg field; +reg [Y_BITS-1:0] v_total; +reg [Y_BITS-1:0] v_fp; +reg [Y_BITS-1:0] v_bp; +reg [Y_BITS-1:0] v_sync; +reg [X_BITS-1:0] hv_offset; + +assign clk_out = !clk; + +/* horizontal counter */ +always @(posedge clk) + if (reset) + h_count <= 0; + else + if (h_count < h_total - 1) + h_count <= h_count + 1'd1; + else + h_count <= 0; + +/* vertical counter */ +always @(posedge clk) + if (reset) + v_count <= 0; + else + if (h_count == h_total - 1) + begin + if (v_count == v_total - 1) + v_count <= 0; + else + v_count <= v_count + 1'd1; + end + +/* field */ +always @(posedge clk) + if (reset) + begin + field <= 0; + v_total <= v_total_0; + v_fp <= interlaced ? v_fp_1 : v_fp_0; // In the interlaced mode this value must be inverted as v_fp_1 is still in field0 + v_bp <= v_bp_0; + v_sync <= v_sync_0; + hv_offset <= hv_offset_0; + end + else + if ((interlaced) && ((v_count == v_total - 1) && (h_count == h_total - 1))) + begin + field <= field + interlaced; + v_total <= field ? v_total_0 : v_total_1; + v_fp <= field ? v_fp_1 : v_fp_0; // This order is inverted as v_fp_1 is still in field0 + v_bp <= field ? v_bp_0 : v_bp_1; + v_sync <= field ? v_sync_0 : v_sync_1; + hv_offset <= field ? hv_offset_0 : hv_offset_1; + end + +always @(posedge clk) + if (reset) + { vs_out, hs_out, hde_out, vde_out, field_out } <= 4'b0; + else begin + hs_out <= ((h_count < h_sync)); + + hde_out <= (h_count >= h_sync + h_bp) && (h_count <= h_total - h_fp - 1); + vde_out <= (v_count >= v_sync + v_bp) && (v_count <= v_total - v_fp - 1); + + if ((v_count == 0) && (h_count == hv_offset)) + vs_out <= 1'b1; + else if ((v_count == v_sync) && (h_count == hv_offset)) + vs_out <= 1'b0; + + /* H_COUNT_OUT and V_COUNT_OUT */ + h_count_out <= h_count; + if (field) + v_count_out <= v_count + v_total_0; + else + v_count_out <= v_count; + + /* X and Y coords � for a backend pattern generator */ + x_out <= h_count - (h_sync + h_bp); + if (interlaced) + y_out <= { (v_count - (v_sync + v_bp)) , field }; + else + y_out <= { 1'b0, (v_count - (v_sync + v_bp)) }; + field_out <= field; + + end + +endmodule diff --git a/sys/sys.qip b/sys/sys.qip new file mode 100644 index 0000000..0697df2 --- /dev/null +++ b/sys/sys.qip @@ -0,0 +1,20 @@ +set_global_assignment -name VERILOG_FILE sys/sys_top.v +set_global_assignment -name SDC_FILE sys/sys_top.sdc +set_global_assignment -name QIP_FILE sys/pll.qip +set_global_assignment -name QIP_FILE sys/pll_hdmi.qip +set_global_assignment -name SYSTEMVERILOG_FILE sys/sdram.sv +set_global_assignment -name SYSTEMVERILOG_FILE sys/ddram.sv +set_global_assignment -name SYSTEMVERILOG_FILE sys/hq2x.sv +set_global_assignment -name VERILOG_FILE sys/scandoubler.v +set_global_assignment -name SYSTEMVERILOG_FILE sys/video_mixer.sv +set_global_assignment -name VERILOG_FILE sys/osd.v +set_global_assignment -name SYSTEMVERILOG_FILE sys/vga_out.sv +set_global_assignment -name VERILOG_FILE sys/sync_vg.v +set_global_assignment -name VERILOG_FILE sys/pattern_vg.v +set_global_assignment -name VERILOG_FILE sys/i2c.v +set_global_assignment -name VERILOG_FILE sys/i2s.v +set_global_assignment -name VERILOG_FILE sys/spdif.v +set_global_assignment -name VERILOG_FILE sys/sigma_delta_dac.v +set_global_assignment -name SYSTEMVERILOG_FILE sys/lpf48k.sv +set_global_assignment -name SYSTEMVERILOG_FILE sys/hdmi_config.sv +set_global_assignment -name VERILOG_FILE sys/hps_io.v diff --git a/sys/sys_top.sdc b/sys/sys_top.sdc new file mode 100644 index 0000000..ecd189a --- /dev/null +++ b/sys/sys_top.sdc @@ -0,0 +1,27 @@ +create_clock -period "50.0 MHz" [get_ports FPGA_CLK1_50] +create_clock -period "50.0 MHz" [get_ports FPGA_CLK2_50] +create_clock -period "50.0 MHz" [get_ports FPGA_CLK3_50] +create_clock -period "100.0 MHz" [get_pins -compatibility_mode *|h2f_user0_clk] + +derive_pll_clocks + +create_generated_clock -source [get_pins -compatibility_mode {*|pll|pll_inst|altera_pll_i|general[1].gpll~PLL_OUTPUT_COUNTER|divclk}] \ + -name SDRAM_CLK [get_ports {SDRAM_CLK}] + +derive_clock_uncertainty + +set_input_delay -max -clock SDRAM_CLK 6.4ns [get_ports SDRAM_DQ[*]] +set_input_delay -min -clock SDRAM_CLK 3.7ns [get_ports SDRAM_DQ[*]] + +set_multicycle_path -from [get_clocks {SDRAM_CLK}] \ + -to [get_clocks {*|pll|pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk}] \ + -setup 2 + +set_output_delay -max -clock SDRAM_CLK 1.6ns [get_ports {SDRAM_D* SDRAM_A* SDRAM_BA* SDRAM_n* SDRAM_CKE}] +set_output_delay -min -clock SDRAM_CLK -0.9ns [get_ports {SDRAM_D* SDRAM_A* SDRAM_BA* SDRAM_n* SDRAM_CKE}] + +set_false_path -from * -to [get_ports {LED_*}] +set_false_path -from * -to [get_ports {BTN_*}] +set_false_path -from * -to [get_ports {VGA_*}] +set_false_path -from * -to [get_ports {AUDIO_L}] +set_false_path -from * -to [get_ports {AUDIO_R}] diff --git a/sys/sys_top.v b/sys/sys_top.v new file mode 100644 index 0000000..130f91c --- /dev/null +++ b/sys/sys_top.v @@ -0,0 +1,681 @@ +//============================================================================ +// +// DE10-nano HAL top module +// (c)2017 Sorgelig +// +// 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. +// +//============================================================================ + +module sys_top +( + /////////// CLOCK ////////// + input FPGA_CLK1_50, + input FPGA_CLK2_50, + input FPGA_CLK3_50, + + //////////// VGA /////////// + output [5:0] VGA_R, + output [5:0] VGA_G, + output [5:0] VGA_B, + output VGA_HS, + output VGA_VS, + input VGA_EN, + + /////////// AUDIO ////////// + output AUDIO_L, + output AUDIO_R, + output AUDIO_SPDIF, + + //////////// HDMI ////////// + output HDMI_I2C_SCL, + inout HDMI_I2C_SDA, + + output HDMI_MCLK, + output HDMI_SCLK, + output HDMI_LRCLK, + output HDMI_I2S, + + output HDMI_TX_CLK, + output HDMI_TX_DE, + output [23:0] HDMI_TX_D, + output HDMI_TX_HS, + output HDMI_TX_VS, + + //////////// SDR /////////// + output [12:0] SDRAM_A, + inout [15:0] SDRAM_DQ, + output SDRAM_DQML, + output SDRAM_DQMH, + output SDRAM_nWE, + output SDRAM_nCAS, + output SDRAM_nRAS, + output SDRAM_nCS, + output [1:0] SDRAM_BA, + output SDRAM_CLK, + output SDRAM_CKE, + + //////////// I/O /////////// + output LED_USER, + output LED_HDD, + output LED_POWER, + input BTN_USER, + input BTN_OSD, + input BTN_RESET, + + //////////// SDIO /////////// + inout [3:0] SDIO_DAT, + inout SDIO_CMD, + output SDIO_CLK, + input SDIO_CD, + + ////////// MB KEY /////////// + input [1:0] KEY, + + ////////// MB LED /////////// + output [7:0] LED +); + + +assign SDIO_DAT[2:1] = 2'bZZ; + +////////////////////////// LEDs /////////////////////////////////////// + +wire led_p = led_power[1] ? ~led_power[0] : 1'b0; +wire led_d = led_disk[1] ? ~led_disk[0] : ~(led_disk[0] | gp_out[29]); +wire led_u = ~led_user; + +assign LED_POWER = led_p ? 1'bZ : 1'b0; +assign LED_HDD = led_d ? 1'bZ : 1'b0; +assign LED_USER = led_u ? 1'bZ : 1'b0; + +//LEDs on main board +assign LED = {3'b000, ~led_p, 1'b0, ~led_d, 1'b0, ~led_u}; + + +////////////////////////// Buttons /////////////////////////////////// +reg btn_user, btn_osd; +always @(posedge FPGA_CLK2_50) begin + integer div; + reg [7:0] deb_user; + reg [7:0] deb_osd; + + div <= div + 1'b1; + if(div > 100000) div <= 0; + + if(!div) begin + deb_user <= {deb_user[6:0], ~(BTN_USER & KEY[1])}; + if(&deb_user) btn_user <= 1; + if(!deb_user) btn_user <= 0; + + deb_osd <= {deb_osd[6:0], ~(BTN_OSD & KEY[0])}; + if(&deb_osd) btn_osd <= 1; + if(!deb_osd) btn_osd <= 0; + end +end + +reg btn_reset = 1; +always @(posedge FPGA_CLK2_50) btn_reset <= BTN_RESET; + + +///////////////////////// HPS I/O ///////////////////////////////////// + +// gp_in[31] = 0 - quick flag that FPGA is initialized (HPS reads 1 when FPGA is not in user mode) +// used to avoid lockups while JTAG loading +wire [31:0] gp_in = {1'b0, btn_user, btn_osd, 9'd0, io_ver, io_ack, io_wide, io_dout}; +wire [31:0] gp_out; + +wire [1:0] io_ver = 1; // 0 - standard MiST I/O (for quick porting of complex MiST cores). 1 - optimized HPS I/O. 2,3 - reserved for future. +wire io_wait; +wire io_wide; +wire [15:0] io_dout; +wire [15:0] io_din = gp_outr[15:0]; +wire io_clk = gp_outr[17]; +wire io_fpga = gp_outr[18]; +wire io_osd = gp_outr[19]; +wire io_uio = gp_outr[20]; +//wire io_sdd = gp_outr[21]; // used only in ST core + +reg io_ack; +reg rack; +wire io_strobe = ~rack & io_clk; + +always @(posedge clk_sys) begin + if(~io_wait | io_strobe) begin + rack <= io_clk; + io_ack <= rack; + end +end + +reg [31:0] gp_outr; +always @(posedge clk_sys) begin + reg [31:0] gp_outd; + gp_outr <= gp_outd; + gp_outd <= gp_out; +end + +wire [7:0] core_type = 'hA4; // A4 - generic core. + +// HPS will not communicate to core if magic is different +wire [31:0] core_magic = {24'h5CA623, core_type}; + +cyclonev_hps_interface_mpu_general_purpose h2f_gp +( + .gp_in({~gp_out[31] ? core_magic : gp_in}), + .gp_out(gp_out) +); + + +reg [15:0] cfg; + +reg cfg_ready = 0; +wire audio_96k = cfg[6]; +wire ypbpr_en = cfg[5]; +wire csync = cfg[3]; +`ifndef LITE +wire vga_scaler= cfg[2]; +`endif + +always@(posedge clk_sys) begin + reg [7:0] cmd; + reg has_cmd; + reg old_strobe; + + old_strobe <= io_strobe; + + if(~io_uio) has_cmd <= 0; + else + if(~old_strobe & io_strobe) begin + if(!has_cmd) begin + has_cmd <= 1; + cmd <= io_din[7:0]; + end + else + if(cmd == 1) begin + cfg <= io_din; + cfg_ready <= 1; + end + end +end + + +/////////////////////////// RESET /////////////////////////////////// + +reg reset_req = 0; +always @(posedge FPGA_CLK2_50) begin + reg [1:0] resetd, resetd2; + reg old_reset; + + //latch the reset + old_reset <= reset; + if(~old_reset & reset) reset_req <= 1; + + //special combination to set/clear the reset + //preventing of accidental reset control + if(resetd==1) reset_req <= 1; + if(resetd==2 && resetd2==0) reset_req <= 0; + + resetd <= gp_out[31:30]; + resetd2 <= resetd; +end + +// 100MHz +wire ctl_clk; + +///////////////////////// VIP version /////////////////////////////// + +`ifndef LITE + +wire reset; +vip vip +( + //Reset/Clock + .reset_reset_req(reset_req), + .reset_reset(reset), + + //DE10-nano has no reset signal on GPIO, so core has to emulate cold reset button. + .reset_cold_req(~btn_reset), + .reset_warm_req(0), + + //control + .ctl_address(ctl_address), + .ctl_write(ctl_write), + .ctl_writedata(ctl_writedata), + .ctl_waitrequest(ctl_waitrequest), + .ctl_clock(ctl_clk), + .ctl_reset(ctl_reset), + + //64-bit DDR3 RAM access + .ramclk1_clk(ram_clk), + .ram1_address(ram_address), + .ram1_burstcount(ram_burstcount), + .ram1_waitrequest(ram_waitrequest), + .ram1_readdata(ram_readdata), + .ram1_readdatavalid(ram_readdatavalid), + .ram1_read(ram_read), + .ram1_writedata(ram_writedata), + .ram1_byteenable(ram_byteenable), + .ram1_write(ram_write), + + //Spare 64-bit DDR3 RAM access + //currently unused + //can combine with ram1 to make a wider RAM bus (although will increase the latency) + .ramclk2_clk(0), + .ram2_address(0), + .ram2_burstcount(0), + .ram2_waitrequest(), + .ram2_readdata(), + .ram2_readdatavalid(), + .ram2_read(0), + .ram2_writedata(0), + .ram2_byteenable(0), + .ram2_write(0), + + //Video input + .in_vid_clk(clk_vid), + .in_vid_data({r_out, g_out, b_out}), + .in_vid_de(de), + .in_vid_v_sync(vs), + .in_vid_h_sync(hs), + .in_vid_datavalid(ce_pix), + .in_vid_locked(1), + .in_vid_f(0), + .in_vid_color_encoding(0), + .in_vid_bit_width(0), + + //HDMI output + .hdmi_vid_clk(~HDMI_TX_CLK), + .hdmi_vid_data(hdmi_data), + .hdmi_vid_datavalid(HDMI_TX_DE), + .hdmi_vid_v_sync(HDMI_TX_VS), + .hdmi_vid_h_sync(HDMI_TX_HS) +); + +wire [8:0] ctl_address; +wire ctl_write; +wire [31:0] ctl_writedata; +wire ctl_waitrequest; +wire ctl_reset; +wire [7:0] ARX, ARY; + +vip_config vip_config +( + .clk(ctl_clk), + .reset(ctl_reset), + + .ARX(ARX), + .ARY(ARY), + + .address(ctl_address), + .write(ctl_write), + .writedata(ctl_writedata), + .waitrequest(ctl_waitrequest) +); +`endif + + +///////////////////////// Lite version //////////////////////////////// + +`ifdef LITE + +wire INTERLACED = 0; +wire [11:0] V_TOTAL_0 = 750; +wire [11:0] V_FP_0 = 5; +wire [11:0] V_BP_0 = 20; +wire [11:0] V_SYNC_0 = 5; +wire [11:0] V_TOTAL_1 = 0; +wire [11:0] V_FP_1 = 0; +wire [11:0] V_BP_1 = 0; +wire [11:0] V_SYNC_1 = 0; +wire [11:0] H_TOTAL = 1650; +wire [11:0] H_FP = 110; +wire [11:0] H_BP = 220; +wire [11:0] H_SYNC = 40; +wire [11:0] HV_OFFSET_0 = 0; +wire [11:0] HV_OFFSET_1 = 0; + +wire [11:0] x; +wire [12:0] y; + +sync_vg #(.X_BITS(12), .Y_BITS(12)) sync_vg +( + .clk(HDMI_TX_CLK), + .reset(reset), + .interlaced(INTERLACED), + .clk_out(), // inverted output clock - unconnected + .v_total_0(V_TOTAL_0), + .v_fp_0(V_FP_0), + .v_bp_0(V_BP_0), + .v_sync_0(V_SYNC_0), + .v_total_1(V_TOTAL_1), + .v_fp_1(V_FP_1), + .v_bp_1(V_BP_1), + .v_sync_1(V_SYNC_1), + .h_total(H_TOTAL), + .h_fp(H_FP), + .h_bp(H_BP), + .h_sync(H_SYNC), + .hv_offset_0(HV_OFFSET_0), + .hv_offset_1(HV_OFFSET_1), + .vde_out(vde), + .hde_out(hde), + .vs_out(vs_hdmi), + .v_count_out(), + .h_count_out(), + .x_out(x), + .y_out(y), + .hs_out(hs_hdmi), + .field_out(field) +); + +wire vde, hde; +wire vs_hdmi; +wire hs_hdmi; +wire field; + +pattern_vg +#( + .B(8), // Bits per channel + .X_BITS(12), + .Y_BITS(12), + .FRACTIONAL_BITS(12) // Number of fractional bits for ramp pattern +) +pattern_vg +( + .reset(reset), + .clk_in(HDMI_TX_CLK), + .x(x), + .y(y[11:0]), + .vn_in(vs_hdmi), + .hn_in(hs_hdmi), + .dn_in(vde & hde), + .r_in(0), + .g_in(0), + .b_in(0), + .vn_out(HDMI_TX_VS), + .hn_out(HDMI_TX_HS), + .den_out(HDMI_TX_DE), + .r_out(hdmi_data[23:16]), + .g_out(hdmi_data[15:8]), + .b_out(hdmi_data[7:0]), + .total_active_pix(H_TOTAL - (H_FP + H_BP + H_SYNC)), + .total_active_lines(INTERLACED ? (V_TOTAL_0 - (V_FP_0 + V_BP_0 + V_SYNC_0)) + (V_TOTAL_1 - (V_FP_1 + V_BP_1 + V_SYNC_1)) : (V_TOTAL_0 - (V_FP_0 + V_BP_0 + V_SYNC_0))), // originally: 13'd480 + .pattern(4), + .ramp_step(20'h0333) +); + +wire reset; +sysmem_lite sysmem +( + //Reset/Clock + .reset_reset_req(reset_req), + .reset_reset(reset), + .ctl_clock(ctl_clk), + + //DE10-nano has no reset signal on GPIO, so core has to emulate cold reset button. + .reset_cold_req(~btn_reset), + .reset_warm_req(0), + + //64-bit DDR3 RAM access + .ramclk1_clk(ram_clk), + .ram1_address(ram_address), + .ram1_burstcount(ram_burstcount), + .ram1_waitrequest(ram_waitrequest), + .ram1_readdata(ram_readdata), + .ram1_readdatavalid(ram_readdatavalid), + .ram1_read(ram_read), + .ram1_writedata(ram_writedata), + .ram1_byteenable(ram_byteenable), + .ram1_write(ram_write), + + //Spare 64-bit DDR3 RAM access + //currently unused + //can combine with ram1 to make a wider RAM bus (although will increase the latency) + .ramclk2_clk(0), + .ram2_address(0), + .ram2_burstcount(0), + .ram2_waitrequest(), + .ram2_readdata(), + .ram2_readdatavalid(), + .ram2_read(0), + .ram2_writedata(0), + .ram2_byteenable(0), + .ram2_write(0) +); + +`endif + + +///////////////////////// HDMI output ///////////////////////////////// + +pll_hdmi pll_hdmi +( + .refclk(FPGA_CLK1_50), + .rst(reset), + .outclk_0(HDMI_TX_CLK) +); + +hdmi_config hdmi_config +( + .iCLK(FPGA_CLK1_50), + .iRST_N(cfg_ready), + .I2C_SCL(HDMI_I2C_SCL), + .I2C_SDA(HDMI_I2C_SDA), + + .audio_48k(~audio_96k), + .iRES(4), // 720p + .iAR(1) // Aspect Ratio +); + +wire [23:0] hdmi_data; +osd hdmi_osd +( + .clk_sys(clk_sys), + + .io_osd(io_osd), + .io_strobe(io_strobe), + .io_din(io_din[7:0]), + + .clk_video(HDMI_TX_CLK), + .din(hdmi_data), + .dout(HDMI_TX_D), + .de(HDMI_TX_DE) +); + +assign HDMI_MCLK = 0; +i2s i2s +( + .reset(~cfg_ready), + .clk_sys(FPGA_CLK1_50), + .half_rate(~audio_96k), + + .sclk(HDMI_SCLK), + .lrclk(HDMI_LRCLK), + .sdata(HDMI_I2S), + + //Could inverse the MSB but it will shift 0 level to -MAX level + .left_chan (audio_l >> !audio_s), + .right_chan(audio_r >> !audio_s) +); + + +///////////////////////// VGA output ////////////////////////////////// + +wire [23:0] vga_q; +osd vga_osd +( + .clk_sys(clk_sys), + + .io_osd(io_osd), + .io_strobe(io_strobe), + .io_din(io_din[7:0]), + + .clk_video(clk_vid), + .din(de ? {r_out, g_out, b_out} : 24'd0), + .dout(vga_q), + .de(de) +); + +wire [23:0] vga_o; + +vga_out vga_out +( + .ypbpr_full(1), + .ypbpr_en(ypbpr_en), + .dout(vga_o), +`ifdef LITE + .din(vga_q) +`else + .din(vga_scaler ? HDMI_TX_D : vga_q) +`endif +); + +`ifdef LITE + wire vs1 = vs; + wire hs1 = hs; +`else + wire vs1 = vga_scaler ? HDMI_TX_VS : vs; + wire hs1 = vga_scaler ? HDMI_TX_HS : hs; +`endif + +assign VGA_VS = VGA_EN ? 1'bZ : csync ? 1'b1 : ~vs1; +assign VGA_HS = VGA_EN ? 1'bZ : csync ? ~(vs1 ^ hs1) : ~hs1; +assign VGA_R = VGA_EN ? 6'bZZZZZZ : vga_o[23:18]; +assign VGA_G = VGA_EN ? 6'bZZZZZZ : vga_o[15:10]; +assign VGA_B = VGA_EN ? 6'bZZZZZZ : vga_o[7:2]; + + +///////////////////////// Audio output //////////////////////////////// + +sigma_delta_dac #(15) dac_l +( + .CLK(FPGA_CLK3_50), + .RESET(reset), + .DACin({audio_l[15] ^ audio_s, audio_l[14:0]}), + .DACout(AUDIO_L) +); + +sigma_delta_dac #(15) dac_r +( + .CLK(FPGA_CLK3_50), + .RESET(reset), + .DACin({audio_r[15] ^ audio_s, audio_r[14:0]}), + .DACout(AUDIO_R) +); + +spdif toslink +( + .clk_i(FPGA_CLK3_50), + + .rst_i(reset), + .half_rate(0), + + .audio_l(audio_l >> !audio_s), + .audio_r(audio_r >> !audio_s), + + .spdif_o(AUDIO_SPDIF) +); + + +/////////////////// User module connection //////////////////////////// + +wire [15:0] audio_l, audio_r; +wire audio_s; +wire [7:0] r_out, g_out, b_out; +wire vs, hs, de; +wire clk_sys, clk_vid, ce_pix; + +wire ram_clk; +wire [28:0] ram_address; +wire [7:0] ram_burstcount; +wire ram_waitrequest; +wire [63:0] ram_readdata; +wire ram_readdatavalid; +wire ram_read; +wire [63:0] ram_writedata; +wire [7:0] ram_byteenable; +wire ram_write; + +wire led_user; +wire [1:0] led_power; +wire [1:0] led_disk; + +emu emu +( + .CLK_50M(FPGA_CLK3_50), + .RESET(reset), + .HPS_BUS({ctl_clk, clk_vid, ce_pix, de, hs, vs, io_wait, clk_sys, io_fpga, io_uio, io_strobe, io_wide, io_din, io_dout}), + + .CLK_VIDEO(clk_vid), + .CE_PIXEL(ce_pix), + + .VGA_R(r_out), + .VGA_G(g_out), + .VGA_B(b_out), + .VGA_HS(hs), + .VGA_VS(vs), + .VGA_DE(de), + + .LED_USER(led_user), + .LED_POWER(led_power), + .LED_DISK(led_disk), + +`ifndef LITE + .VIDEO_ARX(ARX), + .VIDEO_ARY(ARY), +`endif + + .AUDIO_L(audio_l), + .AUDIO_R(audio_r), + .AUDIO_S(audio_s), + .TAPE_IN(0), + + // SCK -> CLK + // MOSI -> CMD + // MISO <- DAT0 + // Z -> DAT1 + // Z -> DAT2 + // CS -> DAT3 + + .SD_SCK(SDIO_CLK), + .SD_MOSI(SDIO_CMD), + .SD_MISO(SDIO_DAT[0]), + .SD_CS(SDIO_DAT[3]), + + .DDRAM_CLK(ram_clk), + .DDRAM_ADDR(ram_address), + .DDRAM_BURSTCNT(ram_burstcount), + .DDRAM_BUSY(ram_waitrequest), + .DDRAM_DOUT(ram_readdata), + .DDRAM_DOUT_READY(ram_readdatavalid), + .DDRAM_RD(ram_read), + .DDRAM_DIN(ram_writedata), + .DDRAM_BE(ram_byteenable), + .DDRAM_WE(ram_write), + + .SDRAM_DQ(SDRAM_DQ), + .SDRAM_A(SDRAM_A), + .SDRAM_DQML(SDRAM_DQML), + .SDRAM_DQMH(SDRAM_DQMH), + .SDRAM_BA(SDRAM_BA), + .SDRAM_nCS(SDRAM_nCS), + .SDRAM_nWE(SDRAM_nWE), + .SDRAM_nRAS(SDRAM_nRAS), + .SDRAM_nCAS(SDRAM_nCAS), + .SDRAM_CLK(SDRAM_CLK), + .SDRAM_CKE(SDRAM_CKE) +); + +endmodule diff --git a/sys/sysmem.qip b/sys/sysmem.qip new file mode 100644 index 0000000..6f27d09 --- /dev/null +++ b/sys/sysmem.qip @@ -0,0 +1,2 @@ +set_global_assignment -name SYSTEMVERILOG_FILE sys/sysmem.sv +set_global_assignment -name VERILOG_FILE sys/ip/reset_source.v diff --git a/sys/sysmem.sv b/sys/sysmem.sv new file mode 100644 index 0000000..4f38ca0 --- /dev/null +++ b/sys/sysmem.sv @@ -0,0 +1,519 @@ +`timescale 1 ps / 1 ps +module sysmem_lite +( + input ramclk1_clk, // ramclk1.clk + input [28:0] ram1_address, // ram1.address + input [7:0] ram1_burstcount, // .burstcount + output ram1_waitrequest, // .waitrequest + output [63:0] ram1_readdata, // .readdata + output ram1_readdatavalid, // .readdatavalid + input ram1_read, // .read + input [63:0] ram1_writedata, // .writedata + input [7:0] ram1_byteenable, // .byteenable + input ram1_write, // .write + + input ramclk2_clk, // ramclk2.clk + input [28:0] ram2_address, // ram2.address + input [7:0] ram2_burstcount, // .burstcount + output ram2_waitrequest, // .waitrequest + output [63:0] ram2_readdata, // .readdata + output ram2_readdatavalid, // .readdatavalid + input ram2_read, // .read + input [63:0] ram2_writedata, // .writedata + input [7:0] ram2_byteenable, // .byteenable + input ram2_write, // .write + + output ctl_clock, + input reset_cold_req, // reset.cold_req + output reset_reset, // .reset + input reset_reset_req, // .reset_req + input reset_warm_req // .warm_req +); + +assign ctl_clock = clk_vip_clk; + +wire hps_h2f_reset_reset; // HPS:h2f_rst_n -> Reset_Source:reset_hps +wire reset_source_reset_cold_reset; // Reset_Source:reset_cold -> HPS:f2h_cold_rst_req_n +wire reset_source_reset_warm_reset; // Reset_Source:reset_warm -> HPS:f2h_warm_rst_req_n +wire clk_vip_clk; + +sysmem_HPS_fpga_interfaces fpga_interfaces ( + .f2h_cold_rst_req_n (~reset_source_reset_cold_reset), // f2h_cold_reset_req.reset_n + .f2h_warm_rst_req_n (~reset_source_reset_warm_reset), // f2h_warm_reset_req.reset_n + .h2f_user0_clk (clk_vip_clk), // h2f_user0_clock.clk + .h2f_rst_n (hps_h2f_reset_reset), // h2f_reset.reset_n + .f2h_sdram0_clk (clk_vip_clk), // f2h_sdram0_clock.clk + .f2h_sdram0_ADDRESS (0), // f2h_sdram0_data.address + .f2h_sdram0_BURSTCOUNT (0), // .burstcount + .f2h_sdram0_WAITREQUEST (), // .waitrequest + .f2h_sdram0_READDATA (), // .readdata + .f2h_sdram0_READDATAVALID (), // .readdatavalid + .f2h_sdram0_READ (0), // .read + .f2h_sdram0_WRITEDATA (0), // .writedata + .f2h_sdram0_BYTEENABLE (0), // .byteenable + .f2h_sdram0_WRITE (0), // .write + .f2h_sdram1_clk (ramclk1_clk), // f2h_sdram1_clock.clk + .f2h_sdram1_ADDRESS (ram1_address), // f2h_sdram1_data.address + .f2h_sdram1_BURSTCOUNT (ram1_burstcount), // .burstcount + .f2h_sdram1_WAITREQUEST (ram1_waitrequest), // .waitrequest + .f2h_sdram1_READDATA (ram1_readdata), // .readdata + .f2h_sdram1_READDATAVALID (ram1_readdatavalid), // .readdatavalid + .f2h_sdram1_READ (ram1_read), // .read + .f2h_sdram1_WRITEDATA (ram1_writedata), // .writedata + .f2h_sdram1_BYTEENABLE (ram1_byteenable), // .byteenable + .f2h_sdram1_WRITE (ram1_write), // .write + .f2h_sdram2_clk (ramclk2_clk), // f2h_sdram2_clock.clk + .f2h_sdram2_ADDRESS (ram2_address), // f2h_sdram2_data.address + .f2h_sdram2_BURSTCOUNT (ram2_burstcount), // .burstcount + .f2h_sdram2_WAITREQUEST (ram2_waitrequest), // .waitrequest + .f2h_sdram2_READDATA (ram2_readdata), // .readdata + .f2h_sdram2_READDATAVALID (ram2_readdatavalid), // .readdatavalid + .f2h_sdram2_READ (ram2_read), // .read + .f2h_sdram2_WRITEDATA (ram2_writedata), // .writedata + .f2h_sdram2_BYTEENABLE (ram2_byteenable), // .byteenable + .f2h_sdram2_WRITE (ram2_write) // .write +); + +reset_source reset_source ( + .clk (clk_vip_clk), // clock.clk + .reset_hps (~hps_h2f_reset_reset), // reset_hps.reset + .reset_sys (), // reset_sys.reset + .cold_req (reset_cold_req), // reset_ctl.cold_req + .reset (reset_reset), // .reset + .reset_req (reset_reset_req), // .reset_req + .warm_req (reset_warm_req), // .warm_req + .reset_warm (reset_source_reset_warm_reset), // reset_warm.reset + .reset_cold (reset_source_reset_cold_reset) // reset_cold.reset +); + +endmodule + +`timescale 1 ps / 1 ps +module sysmem +( + input ramclk1_clk, // ramclk1.clk + input [28:0] ram1_address, // ram1.address + input [7:0] ram1_burstcount, // .burstcount + output ram1_waitrequest, // .waitrequest + output [63:0] ram1_readdata, // .readdata + output ram1_readdatavalid, // .readdatavalid + input ram1_read, // .read + input [63:0] ram1_writedata, // .writedata + input [7:0] ram1_byteenable, // .byteenable + input ram1_write, // .write + + input ramclk2_clk, // ramclk2.clk + input [28:0] ram2_address, // ram2.address + input [7:0] ram2_burstcount, // .burstcount + output ram2_waitrequest, // .waitrequest + output [63:0] ram2_readdata, // .readdata + output ram2_readdatavalid, // .readdatavalid + input ram2_read, // .read + input [63:0] ram2_writedata, // .writedata + input [7:0] ram2_byteenable, // .byteenable + input ram2_write, // .write + + input reset_cold_req, // reset.cold_req + output reset_reset, // .reset + input reset_reset_req, // .reset_req + input reset_warm_req, // .warm_req + + input [27:0] ram_vip_address, // ram_vip.address + input [7:0] ram_vip_burstcount, // .burstcount + output ram_vip_waitrequest, // .waitrequest + output [127:0] ram_vip_readdata, // .readdata + output ram_vip_readdatavalid, // .readdatavalid + input ram_vip_read, // .read + input [127:0] ram_vip_writedata, // .writedata + input [15:0] ram_vip_byteenable, // .byteenable + input ram_vip_write, // .write + + output clk_vip_clk, // clk_vip.clk + output reset_vip_reset // reset_vip.reset +); + +wire hps_h2f_reset_reset; // HPS:h2f_rst_n -> Reset_Source:reset_hps +wire reset_source_reset_cold_reset; // Reset_Source:reset_cold -> HPS:f2h_cold_rst_req_n +wire reset_source_reset_warm_reset; // Reset_Source:reset_warm -> HPS:f2h_warm_rst_req_n + +sysmem_HPS_fpga_interfaces fpga_interfaces ( + .f2h_cold_rst_req_n (~reset_source_reset_cold_reset), // f2h_cold_reset_req.reset_n + .f2h_warm_rst_req_n (~reset_source_reset_warm_reset), // f2h_warm_reset_req.reset_n + .h2f_user0_clk (clk_vip_clk), // h2f_user0_clock.clk + .h2f_rst_n (hps_h2f_reset_reset), // h2f_reset.reset_n + .f2h_sdram0_clk (clk_vip_clk), // f2h_sdram0_clock.clk + .f2h_sdram0_ADDRESS (ram_vip_address), // f2h_sdram0_data.address + .f2h_sdram0_BURSTCOUNT (ram_vip_burstcount), // .burstcount + .f2h_sdram0_WAITREQUEST (ram_vip_waitrequest), // .waitrequest + .f2h_sdram0_READDATA (ram_vip_readdata), // .readdata + .f2h_sdram0_READDATAVALID (ram_vip_readdatavalid), // .readdatavalid + .f2h_sdram0_READ (ram_vip_read), // .read + .f2h_sdram0_WRITEDATA (ram_vip_writedata), // .writedata + .f2h_sdram0_BYTEENABLE (ram_vip_byteenable), // .byteenable + .f2h_sdram0_WRITE (ram_vip_write), // .write + .f2h_sdram1_clk (ramclk1_clk), // f2h_sdram1_clock.clk + .f2h_sdram1_ADDRESS (ram1_address), // f2h_sdram1_data.address + .f2h_sdram1_BURSTCOUNT (ram1_burstcount), // .burstcount + .f2h_sdram1_WAITREQUEST (ram1_waitrequest), // .waitrequest + .f2h_sdram1_READDATA (ram1_readdata), // .readdata + .f2h_sdram1_READDATAVALID (ram1_readdatavalid), // .readdatavalid + .f2h_sdram1_READ (ram1_read), // .read + .f2h_sdram1_WRITEDATA (ram1_writedata), // .writedata + .f2h_sdram1_BYTEENABLE (ram1_byteenable), // .byteenable + .f2h_sdram1_WRITE (ram1_write), // .write + .f2h_sdram2_clk (ramclk2_clk), // f2h_sdram2_clock.clk + .f2h_sdram2_ADDRESS (ram2_address), // f2h_sdram2_data.address + .f2h_sdram2_BURSTCOUNT (ram2_burstcount), // .burstcount + .f2h_sdram2_WAITREQUEST (ram2_waitrequest), // .waitrequest + .f2h_sdram2_READDATA (ram2_readdata), // .readdata + .f2h_sdram2_READDATAVALID (ram2_readdatavalid), // .readdatavalid + .f2h_sdram2_READ (ram2_read), // .read + .f2h_sdram2_WRITEDATA (ram2_writedata), // .writedata + .f2h_sdram2_BYTEENABLE (ram2_byteenable), // .byteenable + .f2h_sdram2_WRITE (ram2_write) // .write +); + +reset_source reset_source ( + .clk (clk_vip_clk), // clock.clk + .reset_hps (~hps_h2f_reset_reset), // reset_hps.reset + .reset_sys (reset_vip_reset), // reset_sys.reset + .cold_req (reset_cold_req), // reset_ctl.cold_req + .reset (reset_reset), // .reset + .reset_req (reset_reset_req), // .reset_req + .warm_req (reset_warm_req), // .warm_req + .reset_warm (reset_source_reset_warm_reset), // reset_warm.reset + .reset_cold (reset_source_reset_cold_reset) // reset_cold.reset +); + +endmodule + +module sysmem_HPS_fpga_interfaces +( + // h2f_reset + output wire [1 - 1 : 0 ] h2f_rst_n + + // f2h_cold_reset_req + ,input wire [1 - 1 : 0 ] f2h_cold_rst_req_n + + // f2h_warm_reset_req + ,input wire [1 - 1 : 0 ] f2h_warm_rst_req_n + + // h2f_user0_clock + ,output wire [1 - 1 : 0 ] h2f_user0_clk + + // f2h_sdram0_data + ,input wire [28 - 1 : 0 ] f2h_sdram0_ADDRESS + ,input wire [8 - 1 : 0 ] f2h_sdram0_BURSTCOUNT + ,output wire [1 - 1 : 0 ] f2h_sdram0_WAITREQUEST + ,output wire [128 - 1 : 0 ] f2h_sdram0_READDATA + ,output wire [1 - 1 : 0 ] f2h_sdram0_READDATAVALID + ,input wire [1 - 1 : 0 ] f2h_sdram0_READ + ,input wire [128 - 1 : 0 ] f2h_sdram0_WRITEDATA + ,input wire [16 - 1 : 0 ] f2h_sdram0_BYTEENABLE + ,input wire [1 - 1 : 0 ] f2h_sdram0_WRITE + + // f2h_sdram0_clock + ,input wire [1 - 1 : 0 ] f2h_sdram0_clk + + // f2h_sdram1_data + ,input wire [29 - 1 : 0 ] f2h_sdram1_ADDRESS + ,input wire [8 - 1 : 0 ] f2h_sdram1_BURSTCOUNT + ,output wire [1 - 1 : 0 ] f2h_sdram1_WAITREQUEST + ,output wire [64 - 1 : 0 ] f2h_sdram1_READDATA + ,output wire [1 - 1 : 0 ] f2h_sdram1_READDATAVALID + ,input wire [1 - 1 : 0 ] f2h_sdram1_READ + ,input wire [64 - 1 : 0 ] f2h_sdram1_WRITEDATA + ,input wire [8 - 1 : 0 ] f2h_sdram1_BYTEENABLE + ,input wire [1 - 1 : 0 ] f2h_sdram1_WRITE + + // f2h_sdram1_clock + ,input wire [1 - 1 : 0 ] f2h_sdram1_clk + + // f2h_sdram2_data + ,input wire [29 - 1 : 0 ] f2h_sdram2_ADDRESS + ,input wire [8 - 1 : 0 ] f2h_sdram2_BURSTCOUNT + ,output wire [1 - 1 : 0 ] f2h_sdram2_WAITREQUEST + ,output wire [64 - 1 : 0 ] f2h_sdram2_READDATA + ,output wire [1 - 1 : 0 ] f2h_sdram2_READDATAVALID + ,input wire [1 - 1 : 0 ] f2h_sdram2_READ + ,input wire [64 - 1 : 0 ] f2h_sdram2_WRITEDATA + ,input wire [8 - 1 : 0 ] f2h_sdram2_BYTEENABLE + ,input wire [1 - 1 : 0 ] f2h_sdram2_WRITE + + // f2h_sdram2_clock + ,input wire [1 - 1 : 0 ] f2h_sdram2_clk +); + + +wire [29 - 1 : 0] intermediate; +assign intermediate[0:0] = ~intermediate[1:1]; +assign intermediate[8:8] = intermediate[4:4]|intermediate[7:7]; +assign intermediate[2:2] = intermediate[9:9]; +assign intermediate[3:3] = intermediate[9:9]; +assign intermediate[5:5] = intermediate[9:9]; +assign intermediate[6:6] = intermediate[9:9]; +assign intermediate[10:10] = intermediate[9:9]; +assign intermediate[11:11] = ~intermediate[12:12]; +assign intermediate[17:17] = intermediate[14:14]|intermediate[16:16]; +assign intermediate[13:13] = intermediate[18:18]; +assign intermediate[15:15] = intermediate[18:18]; +assign intermediate[19:19] = intermediate[18:18]; +assign intermediate[20:20] = ~intermediate[21:21]; +assign intermediate[26:26] = intermediate[23:23]|intermediate[25:25]; +assign intermediate[22:22] = intermediate[27:27]; +assign intermediate[24:24] = intermediate[27:27]; +assign intermediate[28:28] = intermediate[27:27]; +assign f2h_sdram0_WAITREQUEST[0:0] = intermediate[0:0]; +assign f2h_sdram1_WAITREQUEST[0:0] = intermediate[11:11]; +assign f2h_sdram2_WAITREQUEST[0:0] = intermediate[20:20]; +assign intermediate[4:4] = f2h_sdram0_READ[0:0]; +assign intermediate[7:7] = f2h_sdram0_WRITE[0:0]; +assign intermediate[9:9] = f2h_sdram0_clk[0:0]; +assign intermediate[14:14] = f2h_sdram1_READ[0:0]; +assign intermediate[16:16] = f2h_sdram1_WRITE[0:0]; +assign intermediate[18:18] = f2h_sdram1_clk[0:0]; +assign intermediate[23:23] = f2h_sdram2_READ[0:0]; +assign intermediate[25:25] = f2h_sdram2_WRITE[0:0]; +assign intermediate[27:27] = f2h_sdram2_clk[0:0]; + +cyclonev_hps_interface_clocks_resets clocks_resets( + .f2h_warm_rst_req_n({ + f2h_warm_rst_req_n[0:0] // 0:0 + }) +,.f2h_pending_rst_ack({ + 1'b1 // 0:0 + }) +,.f2h_dbg_rst_req_n({ + 1'b1 // 0:0 + }) +,.h2f_rst_n({ + h2f_rst_n[0:0] // 0:0 + }) +,.f2h_cold_rst_req_n({ + f2h_cold_rst_req_n[0:0] // 0:0 + }) +,.h2f_user0_clk({ + h2f_user0_clk[0:0] // 0:0 + }) +); + + +cyclonev_hps_interface_dbg_apb debug_apb( + .DBG_APB_DISABLE({ + 1'b0 // 0:0 + }) +,.P_CLK_EN({ + 1'b0 // 0:0 + }) +); + + +cyclonev_hps_interface_tpiu_trace tpiu( + .traceclk_ctl({ + 1'b1 // 0:0 + }) +); + + +cyclonev_hps_interface_boot_from_fpga boot_from_fpga( + .boot_from_fpga_ready({ + 1'b0 // 0:0 + }) +,.boot_from_fpga_on_failure({ + 1'b0 // 0:0 + }) +,.bsel_en({ + 1'b0 // 0:0 + }) +,.csel_en({ + 1'b0 // 0:0 + }) +,.csel({ + 2'b01 // 1:0 + }) +,.bsel({ + 3'b001 // 2:0 + }) +); + + +cyclonev_hps_interface_fpga2hps fpga2hps( + .port_size_config({ + 2'b11 // 1:0 + }) +); + + +cyclonev_hps_interface_hps2fpga hps2fpga( + .port_size_config({ + 2'b11 // 1:0 + }) +); + + +cyclonev_hps_interface_fpga2sdram f2sdram( + .cfg_rfifo_cport_map({ + 16'b0010000100000000 // 15:0 + }) +,.cfg_wfifo_cport_map({ + 16'b0010000100000000 // 15:0 + }) +,.rd_ready_3({ + 1'b1 // 0:0 + }) +,.cmd_port_clk_2({ + intermediate[28:28] // 0:0 + }) +,.rd_ready_2({ + 1'b1 // 0:0 + }) +,.cmd_port_clk_1({ + intermediate[19:19] // 0:0 + }) +,.rd_ready_1({ + 1'b1 // 0:0 + }) +,.cmd_port_clk_0({ + intermediate[10:10] // 0:0 + }) +,.rd_ready_0({ + 1'b1 // 0:0 + }) +,.wrack_ready_2({ + 1'b1 // 0:0 + }) +,.wrack_ready_1({ + 1'b1 // 0:0 + }) +,.wrack_ready_0({ + 1'b1 // 0:0 + }) +,.cmd_ready_2({ + intermediate[21:21] // 0:0 + }) +,.cmd_ready_1({ + intermediate[12:12] // 0:0 + }) +,.cmd_ready_0({ + intermediate[1:1] // 0:0 + }) +,.cfg_port_width({ + 12'b000000010110 // 11:0 + }) +,.rd_valid_3({ + f2h_sdram2_READDATAVALID[0:0] // 0:0 + }) +,.rd_valid_2({ + f2h_sdram1_READDATAVALID[0:0] // 0:0 + }) +,.rd_valid_1({ + f2h_sdram0_READDATAVALID[0:0] // 0:0 + }) +,.rd_clk_3({ + intermediate[22:22] // 0:0 + }) +,.rd_data_3({ + f2h_sdram2_READDATA[63:0] // 63:0 + }) +,.rd_clk_2({ + intermediate[13:13] // 0:0 + }) +,.rd_data_2({ + f2h_sdram1_READDATA[63:0] // 63:0 + }) +,.rd_clk_1({ + intermediate[3:3] // 0:0 + }) +,.rd_data_1({ + f2h_sdram0_READDATA[127:64] // 63:0 + }) +,.rd_clk_0({ + intermediate[2:2] // 0:0 + }) +,.rd_data_0({ + f2h_sdram0_READDATA[63:0] // 63:0 + }) +,.cfg_axi_mm_select({ + 6'b000000 // 5:0 + }) +,.cmd_valid_2({ + intermediate[26:26] // 0:0 + }) +,.cmd_valid_1({ + intermediate[17:17] // 0:0 + }) +,.cmd_valid_0({ + intermediate[8:8] // 0:0 + }) +,.cfg_cport_rfifo_map({ + 18'b000000000011010000 // 17:0 + }) +,.wr_data_3({ + 2'b00 // 89:88 + ,f2h_sdram2_BYTEENABLE[7:0] // 87:80 + ,16'b0000000000000000 // 79:64 + ,f2h_sdram2_WRITEDATA[63:0] // 63:0 + }) +,.wr_data_2({ + 2'b00 // 89:88 + ,f2h_sdram1_BYTEENABLE[7:0] // 87:80 + ,16'b0000000000000000 // 79:64 + ,f2h_sdram1_WRITEDATA[63:0] // 63:0 + }) +,.wr_data_1({ + 2'b00 // 89:88 + ,f2h_sdram0_BYTEENABLE[15:8] // 87:80 + ,16'b0000000000000000 // 79:64 + ,f2h_sdram0_WRITEDATA[127:64] // 63:0 + }) +,.cfg_cport_type({ + 12'b000000111111 // 11:0 + }) +,.wr_data_0({ + 2'b00 // 89:88 + ,f2h_sdram0_BYTEENABLE[7:0] // 87:80 + ,16'b0000000000000000 // 79:64 + ,f2h_sdram0_WRITEDATA[63:0] // 63:0 + }) +,.cfg_cport_wfifo_map({ + 18'b000000000011010000 // 17:0 + }) +,.wr_clk_3({ + intermediate[24:24] // 0:0 + }) +,.wr_clk_2({ + intermediate[15:15] // 0:0 + }) +,.wr_clk_1({ + intermediate[6:6] // 0:0 + }) +,.wr_clk_0({ + intermediate[5:5] // 0:0 + }) +,.cmd_data_2({ + 18'b000000000000000000 // 59:42 + ,f2h_sdram2_BURSTCOUNT[7:0] // 41:34 + ,3'b000 // 33:31 + ,f2h_sdram2_ADDRESS[28:0] // 30:2 + ,intermediate[25:25] // 1:1 + ,intermediate[23:23] // 0:0 + }) +,.cmd_data_1({ + 18'b000000000000000000 // 59:42 + ,f2h_sdram1_BURSTCOUNT[7:0] // 41:34 + ,3'b000 // 33:31 + ,f2h_sdram1_ADDRESS[28:0] // 30:2 + ,intermediate[16:16] // 1:1 + ,intermediate[14:14] // 0:0 + }) +,.cmd_data_0({ + 18'b000000000000000000 // 59:42 + ,f2h_sdram0_BURSTCOUNT[7:0] // 41:34 + ,4'b0000 // 33:30 + ,f2h_sdram0_ADDRESS[27:0] // 29:2 + ,intermediate[7:7] // 1:1 + ,intermediate[4:4] // 0:0 + }) +); + +endmodule diff --git a/sys/vga_out.sv b/sys/vga_out.sv new file mode 100644 index 0000000..e316000 --- /dev/null +++ b/sys/vga_out.sv @@ -0,0 +1,65 @@ + +module vga_out +( + input ypbpr_full, + input ypbpr_en, + + input [23:0] din, + output [23:0] dout +); + +wire [5:0] yuv_full[225] = '{ + 6'd0, 6'd0, 6'd0, 6'd0, 6'd1, 6'd1, 6'd1, 6'd1, + 6'd2, 6'd2, 6'd2, 6'd3, 6'd3, 6'd3, 6'd3, 6'd4, + 6'd4, 6'd4, 6'd5, 6'd5, 6'd5, 6'd5, 6'd6, 6'd6, + 6'd6, 6'd7, 6'd7, 6'd7, 6'd7, 6'd8, 6'd8, 6'd8, + 6'd9, 6'd9, 6'd9, 6'd9, 6'd10, 6'd10, 6'd10, 6'd11, + 6'd11, 6'd11, 6'd11, 6'd12, 6'd12, 6'd12, 6'd13, 6'd13, + 6'd13, 6'd13, 6'd14, 6'd14, 6'd14, 6'd15, 6'd15, 6'd15, + 6'd15, 6'd16, 6'd16, 6'd16, 6'd17, 6'd17, 6'd17, 6'd17, + 6'd18, 6'd18, 6'd18, 6'd19, 6'd19, 6'd19, 6'd19, 6'd20, + 6'd20, 6'd20, 6'd21, 6'd21, 6'd21, 6'd21, 6'd22, 6'd22, + 6'd22, 6'd23, 6'd23, 6'd23, 6'd23, 6'd24, 6'd24, 6'd24, + 6'd25, 6'd25, 6'd25, 6'd25, 6'd26, 6'd26, 6'd26, 6'd27, + 6'd27, 6'd27, 6'd27, 6'd28, 6'd28, 6'd28, 6'd29, 6'd29, + 6'd29, 6'd29, 6'd30, 6'd30, 6'd30, 6'd31, 6'd31, 6'd31, + 6'd31, 6'd32, 6'd32, 6'd32, 6'd33, 6'd33, 6'd33, 6'd33, + 6'd34, 6'd34, 6'd34, 6'd35, 6'd35, 6'd35, 6'd35, 6'd36, + 6'd36, 6'd36, 6'd36, 6'd37, 6'd37, 6'd37, 6'd38, 6'd38, + 6'd38, 6'd38, 6'd39, 6'd39, 6'd39, 6'd40, 6'd40, 6'd40, + 6'd40, 6'd41, 6'd41, 6'd41, 6'd42, 6'd42, 6'd42, 6'd42, + 6'd43, 6'd43, 6'd43, 6'd44, 6'd44, 6'd44, 6'd44, 6'd45, + 6'd45, 6'd45, 6'd46, 6'd46, 6'd46, 6'd46, 6'd47, 6'd47, + 6'd47, 6'd48, 6'd48, 6'd48, 6'd48, 6'd49, 6'd49, 6'd49, + 6'd50, 6'd50, 6'd50, 6'd50, 6'd51, 6'd51, 6'd51, 6'd52, + 6'd52, 6'd52, 6'd52, 6'd53, 6'd53, 6'd53, 6'd54, 6'd54, + 6'd54, 6'd54, 6'd55, 6'd55, 6'd55, 6'd56, 6'd56, 6'd56, + 6'd56, 6'd57, 6'd57, 6'd57, 6'd58, 6'd58, 6'd58, 6'd58, + 6'd59, 6'd59, 6'd59, 6'd60, 6'd60, 6'd60, 6'd60, 6'd61, + 6'd61, 6'd61, 6'd62, 6'd62, 6'd62, 6'd62, 6'd63, 6'd63, + 6'd63 +}; + +wire [5:0] red = din[23:18]; +wire [5:0] green = din[15:10]; +wire [5:0] blue = din[7:2]; + +// http://marsee101.blog19.fc2.com/blog-entry-2311.html +// Y = 16 + 0.257*R + 0.504*G + 0.098*B (Y = 0.299*R + 0.587*G + 0.114*B) +// Pb = 128 - 0.148*R - 0.291*G + 0.439*B (Pb = -0.169*R - 0.331*G + 0.500*B) +// Pr = 128 + 0.439*R - 0.368*G - 0.071*B (Pr = 0.500*R - 0.419*G - 0.081*B) + +wire [18:0] y_8 = 19'd04096 + ({red, 8'd0} + {red, 3'd0}) + ({green, 9'd0} + {green, 2'd0}) + ({blue, 6'd0} + {blue, 5'd0} + {blue, 2'd0}); +wire [18:0] pb_8 = 19'd32768 - ({red, 7'd0} + {red, 4'd0} + {red, 3'd0}) - ({green, 8'd0} + {green, 5'd0} + {green, 3'd0}) + ({blue, 8'd0} + {blue, 7'd0} + {blue, 6'd0}); +wire [18:0] pr_8 = 19'd32768 + ({red, 8'd0} + {red, 7'd0} + {red, 6'd0}) - ({green, 8'd0} + {green, 6'd0} + {green, 5'd0} + {green, 4'd0} + {green, 3'd0}) - ({blue, 6'd0} + {blue , 3'd0}); + +wire [7:0] y = ( y_8[17:8] < 16) ? 8'd16 : ( y_8[17:8] > 235) ? 8'd235 : y_8[15:8]; +wire [7:0] pb = (pb_8[17:8] < 16) ? 8'd16 : (pb_8[17:8] > 240) ? 8'd240 : pb_8[15:8]; +wire [7:0] pr = (pr_8[17:8] < 16) ? 8'd16 : (pr_8[17:8] > 240) ? 8'd240 : pr_8[15:8]; + +assign dout[23:16] = ypbpr_en ? {(ypbpr_full ? yuv_full[pr-8'd16] : pr[7:2]), 2'b00} : din[23:16]; +assign dout[15:8] = ypbpr_en ? {(ypbpr_full ? yuv_full[y -8'd16] : y[7:2]), 2'b00} : din[15:8]; +assign dout[7:0] = ypbpr_en ? {(ypbpr_full ? yuv_full[pb-8'd16] : pb[7:2]), 2'b00} : din[7:0]; + + +endmodule diff --git a/sys/video_mixer.sv b/sys/video_mixer.sv new file mode 100644 index 0000000..6babc3e --- /dev/null +++ b/sys/video_mixer.sv @@ -0,0 +1,167 @@ +// +// +// Copyright (c) 2017 Sorgelig +// +// This program is GPL Licensed. See COPYING for the full license. +// +// +//////////////////////////////////////////////////////////////////////////////////////////////////////// + +`timescale 1ns / 1ps + +// +// LINE_LENGTH: Length of display line in pixels +// Usually it's length from HSync to HSync. +// May be less if line_start is used. +// +// HALF_DEPTH: If =1 then color dept is 4 bits per component +// For half depth 8 bits monochrome is available with +// mono signal enabled and color = {G, R} + +module video_mixer +#( + parameter LINE_LENGTH = 768, + parameter HALF_DEPTH = 0 +) +( + // master clock + // it should be multiple by (ce_pix*4). + input clk_sys, + + // Pixel clock or clock_enable (both are accepted). + input ce_pix, + output ce_pix_out, + + input scandoubler, + + // scanlines (00-none 01-25% 10-50% 11-75%) + input [1:0] scanlines, + + // High quality 2x scaling + input hq2x, + + // color + input [DWIDTH:0] R, + input [DWIDTH:0] G, + input [DWIDTH:0] B, + + // Monochrome mode (for HALF_DEPTH only) + input mono, + + // Positive pulses. + input HSync, + input VSync, + input HBlank, + input VBlank, + + // video output signals + output reg [7:0] VGA_R, + output reg [7:0] VGA_G, + output reg [7:0] VGA_B, + output reg VGA_VS, + output reg VGA_HS, + output reg VGA_DE +); + +localparam DWIDTH = HALF_DEPTH ? 3 : 7; + +wire [DWIDTH:0] R_sd; +wire [DWIDTH:0] G_sd; +wire [DWIDTH:0] B_sd; +wire hs_sd, vs_sd, hb_sd, vb_sd, ce_pix_sd; + +scandoubler #(.LENGTH(LINE_LENGTH), .HALF_DEPTH(HALF_DEPTH)) sd +( + .*, + .hs_in(HSync), + .vs_in(VSync), + .hb_in(HBlank), + .vb_in(VBlank), + .r_in(R), + .g_in(G), + .b_in(B), + + .ce_pix_out(ce_pix_sd), + .hs_out(hs_sd), + .vs_out(vs_sd), + .hb_out(hb_sd), + .vb_out(vb_sd), + .r_out(R_sd), + .g_out(G_sd), + .b_out(B_sd) +); + +wire [DWIDTH:0] rt = (scandoubler ? R_sd : R); +wire [DWIDTH:0] gt = (scandoubler ? G_sd : G); +wire [DWIDTH:0] bt = (scandoubler ? B_sd : B); + +generate + if(HALF_DEPTH) begin + wire [7:0] r = mono ? {gt,rt} : {rt,rt}; + wire [7:0] g = mono ? {gt,rt} : {gt,gt}; + wire [7:0] b = mono ? {gt,rt} : {bt,bt}; + end else begin + wire [7:0] r = rt; + wire [7:0] g = gt; + wire [7:0] b = bt; + end +endgenerate + +wire hs = (scandoubler ? hs_sd : HSync); +wire vs = (scandoubler ? vs_sd : VSync); + +assign ce_pix_out = scandoubler ? ce_pix_sd : ce_pix; + + +reg scanline = 0; +always @(posedge clk_sys) begin + reg old_hs, old_vs; + + old_hs <= hs; + old_vs <= vs; + + if(old_hs && ~hs) scanline <= ~scanline; + if(old_vs && ~vs) scanline <= 0; +end + +wire hde = scandoubler ? ~hb_sd : ~HBlank; +wire vde = scandoubler ? ~vb_sd : ~VBlank; + +always @(posedge clk_sys) begin + reg old_hde; + + case(scanlines & {scanline, scanline}) + 1: begin // reduce 25% = 1/2 + 1/4 + VGA_R <= {1'b0, r[7:1]} + {2'b00, r[7:2]}; + VGA_G <= {1'b0, g[7:1]} + {2'b00, g[7:2]}; + VGA_B <= {1'b0, b[7:1]} + {2'b00, b[7:2]}; + end + + 2: begin // reduce 50% = 1/2 + VGA_R <= {1'b0, r[7:1]}; + VGA_G <= {1'b0, g[7:1]}; + VGA_B <= {1'b0, b[7:1]}; + end + + 3: begin // reduce 75% = 1/4 + VGA_R <= {2'b00, r[7:2]}; + VGA_G <= {2'b00, g[7:2]}; + VGA_B <= {2'b00, b[7:2]}; + end + + default: begin + VGA_R <= r; + VGA_G <= g; + VGA_B <= b; + end + endcase + + VGA_VS <= vs; + VGA_HS <= hs; + + old_hde <= hde; + if(~old_hde && hde && vde) VGA_DE <= 1; + if(old_hde && ~hde) VGA_DE <= 0; +end + +endmodule diff --git a/sys/vip.qip b/sys/vip.qip new file mode 100644 index 0000000..abbb0dc --- /dev/null +++ b/sys/vip.qip @@ -0,0 +1,2 @@ +set_global_assignment -name SYSTEMVERILOG_FILE sys/vip_config.sv +set_global_assignment -name QIP_FILE sys/vip/synthesis/vip.qip diff --git a/sys/vip.qsys b/sys/vip.qsys new file mode 100644 index 0000000..4a96e70 --- /dev/null +++ b/sys/vip.qsys @@ -0,0 +1,1097 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + No,No,No,No,No,No,No,No + + + + + + + + + + + + + + + + + + + + + Avalon-MM Bidirectional,Avalon-MM Bidirectional,Avalon-MM Bidirectional + + + + + + + + + + + + + + + + + + + + + + + + + + + + + No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No + + + + + + + + + + + + + + + + No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No,No + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {320000000 1600000000} {320000000 1000000000} {800000000 400000000 400000000} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sys/vip_config.sv b/sys/vip_config.sv new file mode 100644 index 0000000..d5349b6 --- /dev/null +++ b/sys/vip_config.sv @@ -0,0 +1,169 @@ + +module vip_config +( + input clk, + input reset, + + input [7:0] ARX, + input [7:0] ARY, + + output reg [8:0] address, + output reg write, + output reg [31:0] writedata, + input waitrequest +); + +//Any input video resolution up to 1920x1080 is supported. + +//Output video parameters. +//It's good to keep 1280x720@60 resolution among all cores as most compatible resolution. +parameter WIDTH = 1280; +parameter HEIGHT = 720; +parameter HFP = 110; +parameter HBP = 220; +parameter HS = 40; +parameter VFP = 5; +parameter VBP = 20; +parameter VS = 5; + + +reg [31:0] wcalc; +reg [31:0] hcalc; + +wire [31:0] videow = (wcalc > WIDTH) ? WIDTH : wcalc; +wire [31:0] videoh = (hcalc > HEIGHT) ? HEIGHT : hcalc; + +wire [31:0] posx = (WIDTH - videow)>>1; +wire [31:0] posy = (HEIGHT- videoh)>>1; + + +always @(posedge clk) begin + reg [7:0] state = 0; + reg [7:0] arx, ary; + integer timeout = 0; + + if(reset || (!state && ((arx != ARX) || (ary != ARY)))) begin + arx <= ARX; + ary <= ARY; + timeout <= 0; + write <= 0; + end + else + if(timeout < 1000000) + begin + timeout <= timeout + 1; + write <= 0; + state <= 1; + end + else + if(~waitrequest && state) + begin + state <= state + 1'd1; + write <= 1; + + case(state) + 01: begin + wcalc <= (HEIGHT*arx)/ary; + hcalc <= (WIDTH*ary)/arx; + end + endcase + + if(state&3) write <= 0; + else + case(state>>2) + //scaler + 01: begin + address <= 'h003; //Output Width + writedata <= videow; + end + 02: begin + address <= 'h004; //Output Height + writedata <= videoh; + end + 03: begin + address <= 'h000; //Go + writedata <= 1; + end + + //mixer + 10: begin + address <= 'h083; //Bkg Width + writedata <= WIDTH; + end + 11: begin + address <= 'h084; //Bkg Height + writedata <= HEIGHT; + end + 12: begin + address <= 'h088; //Pos X + writedata <= posx; + end + 13: begin + address <= 'h089; //Pos Y + writedata <= posy; + end + 14: begin + address <= 'h08A; //Enable Video 0 + writedata <= 1; + end + 15: begin + address <= 'h080; //Go + writedata <= 1; + end + + //video mode + 20: begin + address <= 'h104; //Bank + writedata <= 0; + end + 21: begin + address <= 'h105; //Progressive/Interlaced + writedata <= 0; + end + 22: begin + address <= 'h106; //Active pixel count + writedata <= WIDTH; + end + 23: begin + address <= 'h107; //Active line count + writedata <= HEIGHT; + end + 24: begin + address <= 'h109; //Horizontal Front Porch + writedata <= HFP; + end + 25: begin + address <= 'h10A; //Horizontal Sync Length + writedata <= HS; + end + 26: begin + address <= 'h10B; //Horizontal Blanking (HFP+HBP+HSync) + writedata <= HFP+HBP+HS; + end + 27: begin + address <= 'h10C; //Vertical Front Porch + writedata <= VFP; + end + 28: begin + address <= 'h10D; //Vertical Sync Length + writedata <= VS; + end + 29: begin + address <= 'h10E; //Vertical blanking (VFP+VBP+VSync) + writedata <= VFP+VBP+VS; + end + 30: begin + address <= 'h11E; //Valid + writedata <= 1; + end + 31: begin + address <= 'h100; //Go + writedata <= 1; + end + + default: write <= 0; + endcase + end +end + +endmodule diff --git a/via.v b/via.v new file mode 100644 index 0000000..16930b8 --- /dev/null +++ b/via.v @@ -0,0 +1,365 @@ +/* VIA + + This implementation assumes the I/O data directions and PCR edge triggers used in the Macintosh, + and ignores most writes to the VIA data direction registers and the PCR. + + The 16 VIA registers are mapped to addresses {8'hEF, 8'b111xxxx1, 8'hFE}: + 0 $0 vBufB register B + 1 $200 ????? register A (controls handshake) + 2 $400 vDirB register B direction register + 3 $600 vDirA register A direction register + 4 $800 vT1C timer 1 counter (low-order byte) - for sound? + 5 $A00 vT1CH timer 1 counter (high-order byte) + 6 $C00 vT1L timer 1 latch (low-order byte) + 7 $E00 vT1LH timer 1 latch (high-order byte) + 8 $1000 vT2C timer 2 counter (low-order byte) - W: writes T2L-L R: read T2C-L and clear interrupt flag + 9 $1200 vT2CH timer 2 counter (high-order byte) - W: write T2C-H, transfer T2L-L to T2C-L, clear interrupt flag R: read T2C-H + 10 $1400 vSR shift register (keyboard) + 11 $1600 vACR auxiliary control register + 12 $1800 vPCR peripheral control register + 13 $1A00 vIFR interrupt flag register + 14 $1C00 vIER interrupt enable register + 15 $1E00 vBufA register A (no handshake) + + Register A: + Bit(s) Name Dir Description + + 7 vSCCWReq in SCC wait/request + 6 vPage2 out Alternate screen buffer (1 = main buffer) + 5 vHeadSel out Disk SEL line + 4 vOverlay out ROM low-memory overlay (1 = overlay on) + 3 vSndPg2 out Alternate sound buffer (1 = main buffer) + 0-2 vSound (mask) out Sound volume + + Register B: + Bit Name Dir Description + + 7 vSndEnb out Sound enable/disable + 6 vH4 in Horizontal blanking + 5 vY2 in Mouse Y2 + 4 vX2 in Mouse X2 + 3 vSW in Mouse switch + 2 rTCEnb out Real-time clock serial enable (active low I think) + 1 rTCClk out Real-time clock data-clock line + 0 rTCData in/out Real-time clock serial data + + Interrupt flag and enable registers: + IFR bit 7: remains set (and the IRQ line to the processor is held low) as long as any enabled VIA + interrupt is occurring. + IER bit 7: "enable/disable": If bit 7 is a 1, each 1 in bits 0-6 enables the corresponding interrupt; + if bit 7 is a 0, each 1 in bits 0-6 disables that interrupt. In either case, 0's in bits 0-6 do not + change the status of those interrupts. Bit 7 is always read as a 1. + + Bit Interrupting device + + 7 IRQ (IFR) or enable (IER) + 6 Timer 1 timeout + 5 Timer 2 timeout + 4 Keyboard clock (CB1) + 3 Keyboard data bit (CB2) + 2 Keyboard data ready (completion of 8 shifts) (SR) + 1 Vertical blanking interrupt (CA1) + 0 One-second interrupt (CA2) + + Peripheral control register: + Bit Description + + 5-7 CB2 control (keyboard data bit) + 4 CB1 control (keyboard clock) + 1-3 CA2 control (one-second interrupt) + 0 CA1 control (vertical blanking interrupt) + + 1-bit controls: 0 = negative edge trigger (normal Macintosh mode), 1 = positive edge trigger + 3-bit controls: + 000 set IFR on negative edge, clear IFR on read/write from register A/B. Normal Macintosh mode. + 001 set IFR on negative edge + 010 set IFR on positive edge, clear IFR on read/write from register A/B + 011 set IFR on positive edge + 100-111 not used in Macintosh (output mode) + + Auxiliary control register: + Bit Description + 6-7 T1 control, 00 = one-shot mode, output to PB7 disabled, 11 = free running mode, output to PB7 enabled + 5 T2 control, 0 = interval timer in one-shot mode (Mac mode), 1 = counts a predetermined number of pulses on pin PB6 (not used) + 2-4 shift register control + 1 PB latch enable + 0 PA latch enable + + Timer 2: + For Macintosh, always operates as a one-shot inerval timer. + 8 $1000 vT2C W: write T2L-L R: read T2C-L and clear interrupt flag + 9 $1200 vT2CH W: write T2C-H, transfer T2L-L to T2C-L, clear interrupt, arms timer flag R: read T2C-H +*/ + +`define INT_ONESEC 0 +`define INT_VBLANK 1 +`define INT_KEYREADY 2 +`define INT_KEYBIT 3 +`define INT_KEYCLK 4 +`define INT_T2 5 +`define INT_T1 6 + +module via +( + input clk, + input cep, + input cen, + + input _reset, + input selectVIA, + input _cpuRW, + input _cpuUDS, + input [15:0] dataIn, + input [3:0] cpuAddrRegHi, + input _hblank, + input _vblank, + input mouseY2, + input mouseX2, + input mouseButton, + input rtcData, + input sccWReq, + output _irq, + output [15:0] dataOut, + output memoryOverlayOn, + output SEL, // to IWM + + output snd_ena, + output snd_alt, + output [2:0] snd_vol, + + input [7:0] kbd_in_data, + input kbd_in_strobe, + output [7:0] kbd_out_data, + output reg kbd_out_strobe +); + + wire [7:0] dataInHi = dataIn[15:8]; + reg [7:0] dataOutHi; + assign dataOut = { dataOutHi, 8'hEF }; + + reg [7:0] viaADataOut; + reg [7:0] viaBDataOut; + reg viaB0DDR; + reg [6:0] viaIFR; + reg [6:0] viaIER; + reg [7:0] viaACR; + reg [7:0] viaSR; + reg [15:0] viaTimer1Count; + reg [15:0] viaTimer1Latch; + reg [15:0] viaTimer2Count; + reg [7:0] viaTimer2LatchLow; + reg viaTimer2Armed; + + + // shift register can be written by CPU and by external source + /* Write to SR (including external input) */ + assign kbd_out_data = viaSR; + always @(posedge clk or negedge _reset) begin + if (_reset == 1'b0) + viaSR <= 8'b0; + else if(cen) begin + if((selectVIA == 1'b1) && (_cpuUDS == 1'b0) && + (_cpuRW == 1'b0) && (cpuAddrRegHi == 4'hA)) + viaSR <= dataInHi; + + if (viaACR[4:2] == 3'b011 && kbd_in_strobe) + viaSR <= kbd_in_data; + end + end + + /* Generate sr_out_strobe */ + always @(posedge clk or negedge _reset) begin + if (_reset == 1'b0) + kbd_out_strobe <= 1'b0; + else if(cen) begin + if((selectVIA == 1'b1) && (_cpuUDS == 1'b0) && + (_cpuRW == 1'b0) && (cpuAddrRegHi == 4'hA) && + (viaACR[4:2] == 3'b111)) + kbd_out_strobe <= 1; + else + kbd_out_strobe <= 0; + end + end + + // divide by 10 clock divider for the VIA timers: 0.78336 MHz + reg [3:0] clkDiv; + always @(posedge clk) begin + if(cep) begin + if (clkDiv == 4'h9) + clkDiv <= 0; + else + clkDiv <= clkDiv + 1'b1; + end + end + wire timerStrobe = (clkDiv == 0); + + // store previous vblank value, for edge detection + reg _lastVblank; + always @(posedge clk) if(cen) _lastVblank <= _vblank; + + // count vblanks, and set 1 second interrupt after 60 vblanks + reg [5:0] vblankCount; + always @(posedge clk) begin + if(cen) begin + if (_vblank == 1'b0 && _lastVblank == 1'b1) begin + if (vblankCount != 59) begin + vblankCount <= vblankCount + 1'b1; + end + else begin + vblankCount <= 6'h0; + end + end + end + end + assign _irq = (viaIFR & viaIER) == 0 ? 1'b1 : 1'b0; + + // register write + wire loadT2 = selectVIA == 1'b1 && _cpuUDS == 1'b0 && _cpuRW == 1'b0 && cpuAddrRegHi == 4'h9; + always @(posedge clk or negedge _reset) begin + if (_reset == 1'b0) begin + viaB0DDR <= 1'b1; + viaADataOut <= 8'b01111111; + viaBDataOut <= 8'b11111111; + viaIFR <= 7'b0000000; + viaIER <= 7'b0000000; + viaACR <= 8'b00000000; + viaTimer1Count <= 16'h0000; + viaTimer1Latch <= 16'h0000; + viaTimer2Count <= 16'h0000; + viaTimer2LatchLow <= 8'h00; + viaTimer2Armed <= 0; + end + else if(cen) begin + if (selectVIA == 1'b1 && _cpuUDS == 1'b0) begin + if (_cpuRW == 1'b0) begin + // normal register writes + case (cpuAddrRegHi) + 4'h0: // B + viaBDataOut <= dataInHi; + 4'h2: // B DDR + viaB0DDR <= dataInHi[0]; + // 4'h3: ignore A DDR + 4'h4: // timer 1 count low + viaTimer1Count[7:0] <= dataInHi; + 4'h5: // timer 1 count high + viaTimer1Count[15:8] <= dataInHi; + 4'h6: // timer 1 latch low + viaTimer1Latch[7:0] <= dataInHi; + 4'h7: // timer 1 latch high + viaTimer1Latch[15:8] <= dataInHi; + 4'h8: // timer 2 latch low + viaTimer2LatchLow <= dataInHi; + 4'h9: begin // timer 2 count high + viaTimer2Count[15:8] <= dataInHi; + viaTimer2Count[7:0] <= viaTimer2LatchLow; + viaTimer2Armed = 1'b1; + viaIFR[`INT_T2] <= 1'b0; + end + 4'hA: begin // shift register + if( viaACR[4:2] == 3'b111 ) + viaIFR[`INT_KEYREADY] <= 1'b1; + end + 4'hB: // Aux control register + viaACR <= dataInHi; + // 4'hC: ignore PCR + 4'hD: // IFR + viaIFR <= viaIFR & ~dataInHi[6:0]; + 4'hE: // IER + if (dataInHi[7]) + viaIER <= viaIER | dataInHi[6:0]; + else + viaIER <= viaIER & ~dataInHi[6:0]; + 4'hF: // A + viaADataOut <= dataInHi; + endcase + end + else begin + // interrupt flag modifications due to register reads + case (cpuAddrRegHi) + 4'h0: begin // reading (and writing?) register B clears KEYCLK and KEYBIT interrupt flags + viaIFR[`INT_KEYCLK] <= 1'b0; + viaIFR[`INT_KEYBIT] <= 1'b0; + end + 4'h8: // reading T2C-L clears the T2 interrupt flag + viaIFR[`INT_T2] <= 1'b0; + 4'hA: // reading SR clears the SR interrupt flag + viaIFR[`INT_KEYREADY] <= 1'b0; + 4'hF: begin // reading (and writing?) register A clears VBLANK and ONESEC interrupt flags + viaIFR[`INT_ONESEC] <= 1'b0; + viaIFR[`INT_VBLANK] <= 1'b0; + end + endcase + end + end + // external interrupts + if (_vblank == 1'b0 && _lastVblank == 1'b1) begin + viaIFR[`INT_VBLANK] <= 1'b1; // set vblank interrupt + if (vblankCount == 59) + viaIFR[`INT_ONESEC] <= 1'b1; // set one second interrupt after 60 vblanks + end + // timer 2 + if (timerStrobe && !loadT2) begin + if (viaTimer2Armed && viaTimer2Count == 0) begin + viaIFR[`INT_T2] <= 1'b1; + viaTimer2Armed <= 0; + end + viaTimer2Count <= viaTimer2Count - 1'b1; + end + + // Shift in under control of external clock + if (viaACR[4:2] == 3'b011 && kbd_in_strobe) + viaIFR[`INT_KEYREADY] <= 1; + + end + end + + // register read + always @(*) begin + dataOutHi = 8'hBE; + + case (cpuAddrRegHi) + 4'h0: // B + // TODO: clear CB1 and CB2 interrupts + dataOutHi = { viaBDataOut[7], ~_hblank, mouseY2, mouseX2, mouseButton, viaBDataOut[2:1], viaB0DDR == 1'b1 ? viaBDataOut[0] : rtcData }; + 4'h2: // B DDR + dataOutHi = { 7'b1000011, viaB0DDR }; + 4'h3: // A DDR + dataOutHi = 8'b01111111; + 4'h4: // timer 1 count low + dataOutHi = viaTimer1Count[7:0]; + 4'h5: // timer 1 count high + dataOutHi = viaTimer1Count[15:8]; + 4'h6: // timer 1 latch low + dataOutHi = viaTimer1Latch[7:0]; + 4'h7: // timer 1 latch high + dataOutHi = viaTimer1Latch[15:8]; + 4'h8: // timer 2 count low + dataOutHi = viaTimer2Count[7:0]; + 4'h9: // timer 2 count high + dataOutHi = viaTimer2Count[15:8]; + 4'hA: // shift register + dataOutHi = viaSR; + 4'hB: // Aux control register + dataOutHi = viaACR; + 4'hC: // PCR + dataOutHi = 0; + 4'hD: // IFR + dataOutHi = { viaIFR & viaIER == 0 ? 1'b0 : 1'b1, viaIFR }; + 4'hE: // IER + dataOutHi = { 1'b1, viaIER }; + 4'hF: // A + // TODO: clear CA1 and CA2 interrupts + dataOutHi = { sccWReq, viaADataOut[6:0] }; + default: + dataOutHi = 8'hBE; + endcase + end + + assign snd_vol = viaADataOut[2:0]; + assign snd_alt = !viaADataOut[3]; + assign snd_ena = viaBDataOut[7]; + + assign memoryOverlayOn = viaADataOut[4]; + assign SEL = viaADataOut[5]; + +endmodule diff --git a/video.v b/video.v new file mode 100644 index 0000000..a688e36 --- /dev/null +++ b/video.v @@ -0,0 +1,163 @@ + +module video +( + input clk, + input ce, + + input [14:0] addr, + input [15:0] dataIn, + input [1:0] wr, + + output reg hsync, + output reg vsync, + output _hblank, + output _vblank, + + output video_en, + output pixelOut +); + +localparam kVisibleWidth = 128, + kTotalWidth = 176, + kVisibleHeightStart = 21, + kVisibleHeightEnd = 362, + kTotalHeight = 370, + kHsyncStart = 135, + kHsyncEnd = 151, + kVsyncStart = 365, + kVsyncEnd = 369, + kPixelLatency = 1; // number of clk8 cycles from xpos==0 to when pixel data actually exits the video shift register + +localparam videoStart = 'hA700 - (kVisibleHeightStart * kVisibleWidth/2); + +reg [7:0] xpos; +reg [9:0] ypos; + +assign _hblank = ~(xpos >= kVisibleWidth); +assign _vblank = ~(ypos < kVisibleHeightStart || ypos > kVisibleHeightEnd); + +wire [15:0] scrData; +vram buff +( + .clock(clk), + + .data(dataIn), + .wraddress(addr[13:0]), + .byteena_a(wr), + .wren(ram_wr), + + .rdaddress(videoStart[14:1] + {ypos[8:0], xpos[6:2]}), + .q(scrData) +); + +reg ram_wr; +always @(posedge clk) begin + reg old_wr; + + old_wr <= |wr; + ram_wr <= (~old_wr & |wr); +end + +reg [3:0] cycle; +always @(posedge clk) if(ce) cycle <= cycle + 1'd1; + +always @(posedge clk) begin + if(ce && !cycle[1:0]) begin + if (xpos == kTotalWidth-1) begin + xpos <= 0; + if (ypos == kTotalHeight-1) ypos <= 0; + else ypos <= ypos + 1'b1; + end else if (!xpos && cycle) begin + xpos <= 0; + end else begin + xpos <= xpos + 1'b1; + end + + hsync <= (xpos >= kHsyncStart+kPixelLatency && xpos <= kHsyncEnd+kPixelLatency); + vsync <= (ypos >= kVsyncStart && ypos <= kVsyncEnd); + end +end + +// a 0 bit is white, and a 1 bit is black +// data is shifted out MSB first +assign pixelOut = ~shiftRegister[15]; +assign video_en = paper[15]; + +reg [15:0] shiftRegister; +reg [15:0] paper; +always @(posedge clk) begin + if(ce) begin + if(_vblank && _hblank && cycle == 2) begin + shiftRegister <= scrData; + paper <= 16'hFFFF; + end + else begin + shiftRegister <= { shiftRegister[14:0], 1'b1 }; + paper <= { paper[14:0], 1'b0 }; + end + end +end + +endmodule + +module vram +( + input clock, + + input [15:0] data, + input [13:0] wraddress, + input [1:0] byteena_a, + input wren, + + input [13:0] rdaddress, + output [15:0] q +); + +altsyncram altsyncram_component ( + .address_a (wraddress), + .address_b (rdaddress), + .byteena_a (byteena_a), + .clock0 (clock), + .data_a (data), + .wren_a (wren), + .q_b (q), + .aclr0 (1'b0), + .aclr1 (1'b0), + .addressstall_a (1'b0), + .addressstall_b (1'b0), + .byteena_b (1'b1), + .clock1 (1'b1), + .clocken0 (1'b1), + .clocken1 (1'b1), + .clocken2 (1'b1), + .clocken3 (1'b1), + .data_b ({16{1'b1}}), + .eccstatus (), + .q_a (), + .rden_a (1'b1), + .rden_b (1'b1), + .wren_b (1'b0)); +defparam + altsyncram_component.address_aclr_b = "NONE", + altsyncram_component.address_reg_b = "CLOCK0", + altsyncram_component.byte_size = 8, + altsyncram_component.clock_enable_input_a = "BYPASS", + altsyncram_component.clock_enable_input_b = "BYPASS", + altsyncram_component.clock_enable_output_b = "BYPASS", + altsyncram_component.intended_device_family = "Cyclone V", + altsyncram_component.lpm_type = "altsyncram", + altsyncram_component.numwords_a = 16384, + altsyncram_component.numwords_b = 16384, + altsyncram_component.operation_mode = "DUAL_PORT", + altsyncram_component.outdata_aclr_b = "NONE", + altsyncram_component.outdata_reg_b = "UNREGISTERED", + altsyncram_component.power_up_uninitialized = "FALSE", + altsyncram_component.read_during_write_mode_mixed_ports = "DONT_CARE", + altsyncram_component.widthad_a = 14, + altsyncram_component.widthad_b = 14, + altsyncram_component.width_a = 16, + altsyncram_component.width_b = 16, + altsyncram_component.width_byteena_a = 2; + + +endmodule