commit c5c7069d553f8e360fddeff1e2555c19eb215e39 Author: sorgelig Date: Mon Oct 16 02:07:56 2017 +0800 Initial port. 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/Archie-lite.qsf b/Archie-lite.qsf new file mode 100644 index 0000000..4461404 --- /dev/null +++ b/Archie-lite.qsf @@ -0,0 +1,393 @@ +# -------------------------------------------------------------------------- # +# +# 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 OFF +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 "AUTO FIT" +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 fdc1772.v +set_global_assignment -name VERILOG_FILE latches.v +set_global_assignment -name VERILOG_FILE floppy.v +set_global_assignment -name VERILOG_FILE podules.v +set_global_assignment -name VERILOG_FILE vidc_audio.v +set_global_assignment -name VERILOG_FILE vidc_dmachannel.v +set_global_assignment -name VERILOG_FILE serialInterface.v +set_global_assignment -name VERILOG_FILE registerInterface.v +set_global_assignment -name VERILOG_FILE i2cSlaveTop.v +set_global_assignment -name VERILOG_FILE i2cSlave.v +set_global_assignment -name VERILOG_FILE ioc_irq.v +set_global_assignment -name VERILOG_FILE ioc.v +set_global_assignment -name VERILOG_FILE memc_translator.v +set_global_assignment -name VERILOG_FILE vidc_fifo.v +set_global_assignment -name VERILOG_FILE sram_line_en.v +set_global_assignment -name VERILOG_FILE vidc_timing.v +set_global_assignment -name VERILOG_FILE vidc.v +set_global_assignment -name VERILOG_FILE memc.v +set_global_assignment -name VERILOG_FILE sdram_top.v +set_global_assignment -name VERILOG_FILE sdram_init.v +set_global_assignment -name VERILOG_FILE amber/a23_barrel_shift.v +set_global_assignment -name VERILOG_FILE amber/a23_wishbone.v +set_global_assignment -name VERILOG_FILE amber/a23_register_bank.v +set_global_assignment -name VERILOG_FILE amber/a23_multiply.v +set_global_assignment -name VERILOG_FILE amber/a23_fetch.v +set_global_assignment -name VERILOG_FILE amber/a23_execute.v +set_global_assignment -name VERILOG_FILE amber/a23_decode.v +set_global_assignment -name VERILOG_FILE amber/a23_core.v +set_global_assignment -name VERILOG_FILE amber/a23_coprocessor.v +set_global_assignment -name VERILOG_FILE amber/a23_config_defines.v +set_global_assignment -name VERILOG_FILE amber/a23_cache.v +set_global_assignment -name VERILOG_FILE amber/a23_alu.v +set_global_assignment -name VERILOG_FILE archimedes_top.v +set_global_assignment -name VERILOG_FILE sram_byte_en.v +set_global_assignment -name SYSTEMVERILOG_FILE Archie.sv +set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/Archie-lite.srf b/Archie-lite.srf new file mode 100644 index 0000000..8aa3b1b --- /dev/null +++ b/Archie-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/Archie.qpf b/Archie.qpf new file mode 100644 index 0000000..ebd3bcf --- /dev/null +++ b/Archie.qpf @@ -0,0 +1,13 @@ +# +# please keep this file read-only! +# Quartus changes this file everytime revision is switched, +# and it will be marked as changed with every commit. +# + +QUARTUS_VERSION = "16.1" +DATE = "23:13:02 April 27, 2017" + +# Revisions + +PROJECT_REVISION = "Archie" +PROJECT_REVISION = "Archie-lite" diff --git a/Archie.qsf b/Archie.qsf new file mode 100644 index 0000000..3b8ce6f --- /dev/null +++ b/Archie.qsf @@ -0,0 +1,392 @@ +# -------------------------------------------------------------------------- # +# +# 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 OFF +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 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 OPTIMIZATION_MODE "AGGRESSIVE PERFORMANCE" +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 fdc1772.v +set_global_assignment -name VERILOG_FILE latches.v +set_global_assignment -name VERILOG_FILE floppy.v +set_global_assignment -name VERILOG_FILE podules.v +set_global_assignment -name VERILOG_FILE vidc_audio.v +set_global_assignment -name VERILOG_FILE vidc_dmachannel.v +set_global_assignment -name VERILOG_FILE serialInterface.v +set_global_assignment -name VERILOG_FILE registerInterface.v +set_global_assignment -name VERILOG_FILE i2cSlaveTop.v +set_global_assignment -name VERILOG_FILE i2cSlave.v +set_global_assignment -name VERILOG_FILE ioc_irq.v +set_global_assignment -name VERILOG_FILE ioc.v +set_global_assignment -name VERILOG_FILE memc_translator.v +set_global_assignment -name VERILOG_FILE vidc_fifo.v +set_global_assignment -name VERILOG_FILE sram_line_en.v +set_global_assignment -name VERILOG_FILE vidc_timing.v +set_global_assignment -name VERILOG_FILE vidc.v +set_global_assignment -name VERILOG_FILE memc.v +set_global_assignment -name VERILOG_FILE sdram_top.v +set_global_assignment -name VERILOG_FILE sdram_init.v +set_global_assignment -name VERILOG_FILE amber/a23_barrel_shift.v +set_global_assignment -name VERILOG_FILE amber/a23_wishbone.v +set_global_assignment -name VERILOG_FILE amber/a23_register_bank.v +set_global_assignment -name VERILOG_FILE amber/a23_multiply.v +set_global_assignment -name VERILOG_FILE amber/a23_fetch.v +set_global_assignment -name VERILOG_FILE amber/a23_execute.v +set_global_assignment -name VERILOG_FILE amber/a23_decode.v +set_global_assignment -name VERILOG_FILE amber/a23_core.v +set_global_assignment -name VERILOG_FILE amber/a23_coprocessor.v +set_global_assignment -name VERILOG_FILE amber/a23_config_defines.v +set_global_assignment -name VERILOG_FILE amber/a23_cache.v +set_global_assignment -name VERILOG_FILE amber/a23_alu.v +set_global_assignment -name VERILOG_FILE archimedes_top.v +set_global_assignment -name VERILOG_FILE sram_byte_en.v +set_global_assignment -name SYSTEMVERILOG_FILE Archie.sv +set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/Archie.srf b/Archie.srf new file mode 100644 index 0000000..04c03cc --- /dev/null +++ b/Archie.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/Archie.sv b/Archie.sv new file mode 100644 index 0000000..c447d2d --- /dev/null +++ b/Archie.sv @@ -0,0 +1,376 @@ +//============================================================================ +// Acorn Archimedes +// +// 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 = 0; +assign LED_DISK = 0; +assign LED_POWER = 0; + +assign VIDEO_ARX = status[1] ? 8'd16 : 8'd4; +assign VIDEO_ARY = status[1] ? 8'd9 : 8'd3; + +`include "build_id.v" +localparam CONF_STR = { + "ARCHIE;;", + "V,v1.00.",`BUILD_DATE +}; + +//////////////////// CLOCKS /////////////////// + +wire pll_ready; +wire clk_128m; +wire clk_32m; + +/* + 24, 16, 12, 8 + 25, 16.6, 12.6, 8.3 + 36, 24, 18, 12 + 24, 16, 12, 8 +*/ + +assign CLK_VIDEO = CLK_50M; + +pll pll +( + .refclk(CLK_50M), + .rst(0), + .outclk_0(clk_128m), + .outclk_1(clk_32m), + .locked(pll_ready) +); + +wire reset = buttons[1] | ~initReset_n; + +reg initReset_n = 0; +always @(posedge clk_32m) if(loader_active) initReset_n <= 1; + +////////////////// HPS I/O /////////////////// +wire [15:0] joyA; +wire [15:0] joyB; +wire [1:0] buttons; +wire [31:0] status; + +wire [7:0] kbd_out_data; +wire kbd_out_strobe; +wire [7:0] kbd_in_data; +wire kbd_in_strobe; + +wire [31:0] fdc_status_out; +wire [31:0] fdc_status_in; +wire [7:0] fdc_data_in; +wire fdc_data_in_strobe; + +wire loader_active; +wire loader_we; +reg loader_stb = 0; +wire [3:0] loader_sel; +wire [24:0] loader_addr; +wire [31:0] loader_data; + +hps_io #(.STRLEN($size(CONF_STR)>>3)) hps_io +( + .clk_sys(clk_32m), + .HPS_BUS(HPS_BUS), + + .conf_str(CONF_STR), + + .joystick_0(joyA), + .joystick_1(joyB), + + .buttons(buttons), + .status(status), + + .kbd_out_data(kbd_out_data), + .kbd_out_strobe(kbd_out_strobe), + .kbd_in_data(kbd_in_data), + .kbd_in_strobe(kbd_in_strobe), + + .fdc_status_out(fdc_status_out), + .fdc_status_in(fdc_status_in), + .fdc_data_in_strobe(fdc_data_in_strobe), + .fdc_data_in(fdc_data_in), + + .ioctl_wr(loader_we), + .ioctl_addr(loader_addr), + .ioctl_dout(loader_data), + .ioctl_download(loader_active), + .ioctl_sel(loader_sel), + + .sd_lba(0), + .sd_rd(0), + .sd_wr(0), + .sd_conf(0), + .sd_buff_din(0), + .ioctl_wait(loader_stb) +); + +assign AUDIO_S = 0; +wire [15:0] sample_l, sample_r; + +wire ce_lpf; +always @(negedge clk_32m) begin + reg [3:0] div; + + div <= div + 1'd1; + if(div == 8) div <=0; + + ce_lpf <= !div; +end + +lpf48k lpf48k_l +( + .RESET(0), + .CLK(clk_32m), + .CE(ce_lpf), + + .ENABLE(1), + .IDATA(sample_r), + .ODATA(AUDIO_R) +); + +lpf48k lpf48k_r +( + .RESET(0), + .CLK(clk_32m), + .CE(ce_lpf), + + .ENABLE(1), + .IDATA(sample_l), + .ODATA(AUDIO_L) +); + + +wire [3:0] core_r, core_g, core_b; +wire core_hs, core_vs; + +assign VGA_R = {core_r,core_r}; +assign VGA_G = {core_g,core_g}; +assign VGA_B = {core_b,core_b}; +assign VGA_HS = ~core_hs; +assign VGA_VS = ~core_vs; + +wire core_ack_in; +wire core_stb_out; +wire core_cyc_out; +wire core_we_o; +wire [3:0] core_sel_o; +wire [2:0] core_cti_o; +wire [31:0] core_data_in, core_data_out; +wire [31:0] ram_data_in; +wire [26:2] core_address_out; + +wire [1:0] pixbaseclk_select; + +wire i2c_din, i2c_dout, i2c_clock; + +archimedes_top ARCHIMEDES +( + .CLKCPU_I ( clk_32m ), + .CLKPIX_I ( CLK_VIDEO ), + .CEPIX_O ( CE_PIXEL ), + + .RESET_I (~ram_ready | loader_active | reset), + + .MEM_ACK_I ( core_ack_in ), + .MEM_DAT_I ( core_data_in ), + .MEM_DAT_O ( core_data_out ), + .MEM_ADDR_O ( core_address_out), + .MEM_STB_O ( core_stb_out ), + .MEM_CYC_O ( core_cyc_out ), + .MEM_SEL_O ( core_sel_o ), + .MEM_WE_O ( core_we_o ), + .MEM_CTI_O ( core_cti_o ), + + .HSYNC ( core_hs ), + .VSYNC ( core_vs ), + + .VIDEO_R ( core_r ), + .VIDEO_G ( core_g ), + .VIDEO_B ( core_b ), + .VIDEO_EN ( VGA_DE ), + + .AUDIO_L ( sample_l ), + .AUDIO_R ( sample_r ), + + .I2C_DOUT ( i2c_din ), + .I2C_DIN ( i2c_dout ), + .I2C_CLOCK ( i2c_clock ), + + .DEBUG_LED ( ), + + .FDC_DIO_STATUS_OUT ( fdc_status_out ), + .FDC_DIO_STATUS_IN ( fdc_status_in ), + .FDC_DIN_STROBE ( fdc_data_in_strobe ), + .FDC_DIN ( fdc_data_in ), + + .KBD_OUT_DATA ( kbd_out_data ), + .KBD_OUT_STROBE ( kbd_out_strobe ), + .KBD_IN_DATA ( kbd_in_data ), + .KBD_IN_STROBE ( kbd_in_strobe ), + + .JOYSTICK0 ( joyA[4:0] ), + .JOYSTICK1 ( joyB[4:0] ), + .VIDBASECLK_O ( pixbaseclk_select ), + .VIDSYNCPOL_O ( ) +); + +wire ram_ack; +wire ram_stb; +wire ram_cyc; +wire ram_we; +wire [3:0] ram_sel; +wire [25:0] ram_address; +wire ram_ready; + +sdram_top SDRAM +( + // wishbone interface + .wb_clk (clk_32m ), + .wb_stb (ram_stb ), + .wb_cyc (ram_cyc ), + .wb_we (ram_we ), + .wb_ack (ram_ack ), + + .wb_sel (ram_sel ), + .wb_adr (ram_address ), + .wb_dat_i (ram_data_in ), + .wb_dat_o (core_data_in), + .wb_cti (core_cti_o ), + + // SDRAM Interface + .sd_clk (clk_128m ), + .sd_rst (~pll_ready ), + + .sd_cke (SDRAM_CKE ), + .sd_dq (SDRAM_DQ ), + .sd_addr (SDRAM_A ), + .sd_dqm ({SDRAM_DQMH,SDRAM_DQML}), + .sd_cs_n (SDRAM_nCS ), + .sd_ba (SDRAM_BA ), + .sd_we_n (SDRAM_nWE ), + .sd_ras_n (SDRAM_nRAS ), + .sd_cas_n (SDRAM_nCAS ), + .sd_ready (ram_ready ) +); + +assign SDRAM_CLK = clk_128m; + +i2cSlaveTop CMOS +( + .clk (clk_32m ), + .rst (~pll_ready ), + .sdaIn (i2c_din ), + .sdaOut (i2c_dout ), + .scl (i2c_clock ) +); + +always @(posedge clk_32m) begin + if (loader_we) loader_stb <= 1'b1; + else if (ram_ack) loader_stb <= 1'b0; +end + +assign ram_we = loader_active ? loader_active : core_we_o; +assign ram_sel = loader_active ? loader_sel : core_sel_o; +assign ram_address = loader_active ? {loader_addr[23:2],2'b00} : {core_address_out[23:2],2'b00}; +assign ram_stb = loader_active ? loader_stb : core_stb_out; +assign ram_cyc = loader_active ? loader_stb : core_stb_out; +assign ram_data_in = loader_active ? loader_data : core_data_out; +assign core_ack_in = loader_active ? 1'b0 : ram_ack; + +endmodule diff --git a/amber/a23_alu.v b/amber/a23_alu.v new file mode 100644 index 0000000..416efef --- /dev/null +++ b/amber/a23_alu.v @@ -0,0 +1,174 @@ +////////////////////////////////////////////////////////////////// +// // +// Arithmetic Logic Unit (ALU) for Amber 2 Core // +// // +// This file is part of the Amber project // +// http://www.opencores.org/project,amber // +// // +// Description // +// Supported functions: 32-bit add and subtract, AND, OR, // +// XOR, NOT, Zero extent 8-bit numbers // +// // +// Author(s): // +// - Conor Santifort, csantifort.amber@gmail.com // +// // +////////////////////////////////////////////////////////////////// +// // +// Copyright (C) 2010 Authors and OPENCORES.ORG // +// // +// This source file may be used and distributed without // +// restriction provided that this copyright statement is not // +// removed from the file and that any derivative work contains // +// the original copyright notice and the associated disclaimer. // +// // +// This source file is free software; you can redistribute it // +// and/or modify it under the terms of the GNU Lesser General // +// Public License as published by the Free Software Foundation; // +// either version 2.1 of the License, or (at your option) any // +// later version. // +// // +// This source 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 Lesser General Public License for more // +// details. // +// // +// You should have received a copy of the GNU Lesser General // +// Public License along with this source; if not, download it // +// from http://www.opencores.org/lgpl.shtml // +// // +////////////////////////////////////////////////////////////////// + + +module a23_alu ( + +input [31:0] i_a_in, +input [31:0] i_b_in, +input i_barrel_shift_carry, +input i_status_bits_carry, +input [8:0] i_function, + +output [31:0] o_out, +output [3:0] o_flags // negative, zero, carry, overflow +); + +wire [31:0] a, b, b_not; +wire [31:0] and_out, or_out, xor_out; +wire [31:0] sign_ex8_out, sign_ex_16_out; +wire [31:0] zero_ex8_out, zero_ex_16_out; +wire [32:0] fadder_out; +wire swap_sel; +wire not_sel; +wire [1:0] cin_sel; +wire cout_sel; +wire [3:0] out_sel; +wire carry_in; +wire carry_out; +wire overflow_out; +wire fadder_carry_out; + +assign { swap_sel, not_sel, cin_sel, cout_sel, out_sel } = i_function; + + +// ======================================================== +// A Select +// ======================================================== +assign a = (swap_sel ) ? i_b_in : i_a_in ; + +// ======================================================== +// B Select +// ======================================================== +assign b = (swap_sel ) ? i_a_in : i_b_in ; + +// ======================================================== +// Not Select +// ======================================================== +assign b_not = (not_sel ) ? ~b : b ; + +// ======================================================== +// Cin Select +// ======================================================== +assign carry_in = (cin_sel==2'd0 ) ? 1'd0 : + (cin_sel==2'd1 ) ? 1'd1 : + i_status_bits_carry ; // add with carry + +// ======================================================== +// Cout Select +// ======================================================== +assign carry_out = (cout_sel==1'd0 ) ? fadder_carry_out : + i_barrel_shift_carry ; + +// For non-addition/subtractions that incorporate a shift +// operation, C is set to the last bit +// shifted out of the value by the shifter. + + +// ======================================================== +// Overflow out +// ======================================================== +// Only assert the overflow flag when using the adder +assign overflow_out = out_sel == 4'd1 && + // overflow if adding two positive numbers and get a negative number + ( (!a[31] && !b_not[31] && fadder_out[31]) || + // or adding two negative numbers and get a positive number + (a[31] && b_not[31] && !fadder_out[31]) ); + + +// ======================================================== +// ALU Operations +// ======================================================== + +`ifdef XILINX_FPGA + + // XIlinx Spartan 6 DSP module + `ifdef XILINX_SPARTAN6_FPGA + xs6_addsub_n #(.WIDTH(33)) + `endif + `ifdef XILINX_VIRTEX6_FPGA + xv6_addsub_n #(.WIDTH(33)) + `endif + u_xx_addsub_33( + .i_a ( {1'd0,a} ), + .i_b ( {1'd0,b_not} ), + .i_cin ( carry_in ), + .i_sub ( 1'd0 ), + .o_sum ( fadder_out ), + .o_co ( ) + ); + +`else +assign fadder_out = { 1'd0,a} + {1'd0,b_not} + {32'd0,carry_in}; +`endif + +assign fadder_carry_out = fadder_out[32]; +assign and_out = a & b_not; +assign or_out = a | b_not; +assign xor_out = a ^ b_not; +assign zero_ex8_out = {24'd0, b_not[7:0]}; +assign zero_ex_16_out = {16'd0, b_not[15:0]}; +assign sign_ex8_out = {{24{b_not[7]}}, b_not[7:0]}; +assign sign_ex_16_out = {{16{b_not[15]}}, b_not[15:0]}; + +// ======================================================== +// Out Select +// ======================================================== +assign o_out = out_sel == 4'd0 ? b_not : + out_sel == 4'd1 ? fadder_out[31:0] : + out_sel == 4'd2 ? zero_ex_16_out : + out_sel == 4'd3 ? zero_ex8_out : + out_sel == 4'd4 ? sign_ex_16_out : + out_sel == 4'd5 ? sign_ex8_out : + out_sel == 4'd6 ? xor_out : + out_sel == 4'd7 ? or_out : + and_out ; + +assign o_flags = { o_out[31], // negative + |o_out == 1'd0, // zero + carry_out, // carry + overflow_out // overflow + }; + + +endmodule + + diff --git a/amber/a23_barrel_shift.v b/amber/a23_barrel_shift.v new file mode 100644 index 0000000..3e62a9c --- /dev/null +++ b/amber/a23_barrel_shift.v @@ -0,0 +1,251 @@ +////////////////////////////////////////////////////////////////// +// // +// Barrel Shifter for Amber 2 Core // +// // +// This file is part of the Amber project // +// http://www.opencores.org/project,amber // +// // +// Description // +// Provides 32-bit shifts LSL, LSR, ASR and ROR // +// // +// Author(s): // +// - Conor Santifort, csantifort.amber@gmail.com // +// // +////////////////////////////////////////////////////////////////// +// // +// Copyright (C) 2010 Authors and OPENCORES.ORG // +// // +// This source file may be used and distributed without // +// restriction provided that this copyright statement is not // +// removed from the file and that any derivative work contains // +// the original copyright notice and the associated disclaimer. // +// // +// This source file is free software; you can redistribute it // +// and/or modify it under the terms of the GNU Lesser General // +// Public License as published by the Free Software Foundation; // +// either version 2.1 of the License, or (at your option) any // +// later version. // +// // +// This source 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 Lesser General Public License for more // +// details. // +// // +// You should have received a copy of the GNU Lesser General // +// Public License along with this source; if not, download it // +// from http://www.opencores.org/lgpl.shtml // +// // +////////////////////////////////////////////////////////////////// + + +module a23_barrel_shift ( + +input [31:0] i_in, +input i_carry_in, +input [7:0] i_shift_amount, // uses 8 LSBs of Rs, or a 5 bit immediate constant +input i_shift_imm_zero, // high when immediate shift value of zero selected +input [1:0] i_function, + +output [31:0] o_out, +output o_carry_out + +); + +`include "a23_localparams.v" + + // MSB is carry out +wire [32:0] lsl_out; +wire [32:0] lsr_out; +wire [32:0] asr_out; +wire [32:0] ror_out; + + +// Logical shift right zero is redundant as it is the same as logical shift left zero, so +// the assembler will convert LSR #0 (and ASR #0 and ROR #0) into LSL #0, and allow +// lsr #32 to be specified. + +// lsl #0 is a special case, where the shifter carry out is the old value of the status flags +// C flag. The contents of Rm are used directly as the second operand. +assign lsl_out = i_shift_imm_zero ? {i_carry_in, i_in } : // fall through case + + i_shift_amount == 8'd 0 ? {i_carry_in, i_in } : // fall through case + i_shift_amount == 8'd 1 ? {i_in[31], i_in[30: 0], 1'd0} : + + i_shift_amount == 8'd 2 ? {i_in[30], i_in[29: 0], 2'd0} : + i_shift_amount == 8'd 3 ? {i_in[29], i_in[28: 0], 3'd0} : + i_shift_amount == 8'd 4 ? {i_in[28], i_in[27: 0], 4'd0} : + i_shift_amount == 8'd 5 ? {i_in[27], i_in[26: 0], 5'd0} : + i_shift_amount == 8'd 6 ? {i_in[26], i_in[25: 0], 6'd0} : + i_shift_amount == 8'd 7 ? {i_in[25], i_in[24: 0], 7'd0} : + i_shift_amount == 8'd 8 ? {i_in[24], i_in[23: 0], 8'd0} : + i_shift_amount == 8'd 9 ? {i_in[23], i_in[22: 0], 9'd0} : + i_shift_amount == 8'd10 ? {i_in[22], i_in[21: 0], 10'd0} : + i_shift_amount == 8'd11 ? {i_in[21], i_in[20: 0], 11'd0} : + + i_shift_amount == 8'd12 ? {i_in[20], i_in[19: 0], 12'd0} : + i_shift_amount == 8'd13 ? {i_in[19], i_in[18: 0], 13'd0} : + i_shift_amount == 8'd14 ? {i_in[18], i_in[17: 0], 14'd0} : + i_shift_amount == 8'd15 ? {i_in[17], i_in[16: 0], 15'd0} : + i_shift_amount == 8'd16 ? {i_in[16], i_in[15: 0], 16'd0} : + i_shift_amount == 8'd17 ? {i_in[15], i_in[14: 0], 17'd0} : + i_shift_amount == 8'd18 ? {i_in[14], i_in[13: 0], 18'd0} : + i_shift_amount == 8'd19 ? {i_in[13], i_in[12: 0], 19'd0} : + i_shift_amount == 8'd20 ? {i_in[12], i_in[11: 0], 20'd0} : + i_shift_amount == 8'd21 ? {i_in[11], i_in[10: 0], 21'd0} : + + i_shift_amount == 8'd22 ? {i_in[10], i_in[ 9: 0], 22'd0} : + i_shift_amount == 8'd23 ? {i_in[ 9], i_in[ 8: 0], 23'd0} : + i_shift_amount == 8'd24 ? {i_in[ 8], i_in[ 7: 0], 24'd0} : + i_shift_amount == 8'd25 ? {i_in[ 7], i_in[ 6: 0], 25'd0} : + i_shift_amount == 8'd26 ? {i_in[ 6], i_in[ 5: 0], 26'd0} : + i_shift_amount == 8'd27 ? {i_in[ 5], i_in[ 4: 0], 27'd0} : + i_shift_amount == 8'd28 ? {i_in[ 4], i_in[ 3: 0], 28'd0} : + i_shift_amount == 8'd29 ? {i_in[ 3], i_in[ 2: 0], 29'd0} : + i_shift_amount == 8'd30 ? {i_in[ 2], i_in[ 1: 0], 30'd0} : + i_shift_amount == 8'd31 ? {i_in[ 1], i_in[ 0: 0], 31'd0} : + i_shift_amount == 8'd32 ? {i_in[ 0], 32'd0 } : // 32 + {1'd0, 32'd0 } ; // > 32 + + +// The form of the shift field which might be expected to correspond to LSR #0 is used +// to encode LSR #32, which has a zero result with bit 31 of Rm as the carry output. + // carry out, < -------- out ----------> +assign lsr_out = i_shift_imm_zero ? {i_in[31], 32'd0 } : + + i_shift_amount == 8'd 0 ? {i_carry_in, i_in } : // fall through case + i_shift_amount == 8'd 1 ? {i_in[ 0], 1'd0, i_in[31: 1]} : + i_shift_amount == 8'd 2 ? {i_in[ 1], 2'd0, i_in[31: 2]} : + i_shift_amount == 8'd 3 ? {i_in[ 2], 3'd0, i_in[31: 3]} : + i_shift_amount == 8'd 4 ? {i_in[ 3], 4'd0, i_in[31: 4]} : + i_shift_amount == 8'd 5 ? {i_in[ 4], 5'd0, i_in[31: 5]} : + i_shift_amount == 8'd 6 ? {i_in[ 5], 6'd0, i_in[31: 6]} : + i_shift_amount == 8'd 7 ? {i_in[ 6], 7'd0, i_in[31: 7]} : + i_shift_amount == 8'd 8 ? {i_in[ 7], 8'd0, i_in[31: 8]} : + i_shift_amount == 8'd 9 ? {i_in[ 8], 9'd0, i_in[31: 9]} : + + i_shift_amount == 8'd10 ? {i_in[ 9], 10'd0, i_in[31:10]} : + i_shift_amount == 8'd11 ? {i_in[10], 11'd0, i_in[31:11]} : + i_shift_amount == 8'd12 ? {i_in[11], 12'd0, i_in[31:12]} : + i_shift_amount == 8'd13 ? {i_in[12], 13'd0, i_in[31:13]} : + i_shift_amount == 8'd14 ? {i_in[13], 14'd0, i_in[31:14]} : + i_shift_amount == 8'd15 ? {i_in[14], 15'd0, i_in[31:15]} : + i_shift_amount == 8'd16 ? {i_in[15], 16'd0, i_in[31:16]} : + i_shift_amount == 8'd17 ? {i_in[16], 17'd0, i_in[31:17]} : + i_shift_amount == 8'd18 ? {i_in[17], 18'd0, i_in[31:18]} : + i_shift_amount == 8'd19 ? {i_in[18], 19'd0, i_in[31:19]} : + + i_shift_amount == 8'd20 ? {i_in[19], 20'd0, i_in[31:20]} : + i_shift_amount == 8'd21 ? {i_in[20], 21'd0, i_in[31:21]} : + i_shift_amount == 8'd22 ? {i_in[21], 22'd0, i_in[31:22]} : + i_shift_amount == 8'd23 ? {i_in[22], 23'd0, i_in[31:23]} : + i_shift_amount == 8'd24 ? {i_in[23], 24'd0, i_in[31:24]} : + i_shift_amount == 8'd25 ? {i_in[24], 25'd0, i_in[31:25]} : + i_shift_amount == 8'd26 ? {i_in[25], 26'd0, i_in[31:26]} : + i_shift_amount == 8'd27 ? {i_in[26], 27'd0, i_in[31:27]} : + i_shift_amount == 8'd28 ? {i_in[27], 28'd0, i_in[31:28]} : + i_shift_amount == 8'd29 ? {i_in[28], 29'd0, i_in[31:29]} : + + i_shift_amount == 8'd30 ? {i_in[29], 30'd0, i_in[31:30]} : + i_shift_amount == 8'd31 ? {i_in[30], 31'd0, i_in[31 ]} : + i_shift_amount == 8'd32 ? {i_in[31], 32'd0 } : + {1'd0, 32'd0 } ; // > 32 + + +// The form of the shift field which might be expected to give ASR #0 is used to encode +// ASR #32. Bit 31 of Rm is again used as the carry output, and each bit of operand 2 is +// also equal to bit 31 of Rm. The result is therefore all ones or all zeros, according to +// the value of bit 31 of Rm. + + // carry out, < -------- out ----------> +assign asr_out = i_shift_imm_zero ? {i_in[31], {32{i_in[31]}} } : + + i_shift_amount == 8'd 0 ? {i_carry_in, i_in } : // fall through case + i_shift_amount == 8'd 1 ? {i_in[ 0], { 2{i_in[31]}}, i_in[30: 1]} : + i_shift_amount == 8'd 2 ? {i_in[ 1], { 3{i_in[31]}}, i_in[30: 2]} : + i_shift_amount == 8'd 3 ? {i_in[ 2], { 4{i_in[31]}}, i_in[30: 3]} : + i_shift_amount == 8'd 4 ? {i_in[ 3], { 5{i_in[31]}}, i_in[30: 4]} : + i_shift_amount == 8'd 5 ? {i_in[ 4], { 6{i_in[31]}}, i_in[30: 5]} : + i_shift_amount == 8'd 6 ? {i_in[ 5], { 7{i_in[31]}}, i_in[30: 6]} : + i_shift_amount == 8'd 7 ? {i_in[ 6], { 8{i_in[31]}}, i_in[30: 7]} : + i_shift_amount == 8'd 8 ? {i_in[ 7], { 9{i_in[31]}}, i_in[30: 8]} : + i_shift_amount == 8'd 9 ? {i_in[ 8], {10{i_in[31]}}, i_in[30: 9]} : + + i_shift_amount == 8'd10 ? {i_in[ 9], {11{i_in[31]}}, i_in[30:10]} : + i_shift_amount == 8'd11 ? {i_in[10], {12{i_in[31]}}, i_in[30:11]} : + i_shift_amount == 8'd12 ? {i_in[11], {13{i_in[31]}}, i_in[30:12]} : + i_shift_amount == 8'd13 ? {i_in[12], {14{i_in[31]}}, i_in[30:13]} : + i_shift_amount == 8'd14 ? {i_in[13], {15{i_in[31]}}, i_in[30:14]} : + i_shift_amount == 8'd15 ? {i_in[14], {16{i_in[31]}}, i_in[30:15]} : + i_shift_amount == 8'd16 ? {i_in[15], {17{i_in[31]}}, i_in[30:16]} : + i_shift_amount == 8'd17 ? {i_in[16], {18{i_in[31]}}, i_in[30:17]} : + i_shift_amount == 8'd18 ? {i_in[17], {19{i_in[31]}}, i_in[30:18]} : + i_shift_amount == 8'd19 ? {i_in[18], {20{i_in[31]}}, i_in[30:19]} : + + i_shift_amount == 8'd20 ? {i_in[19], {21{i_in[31]}}, i_in[30:20]} : + i_shift_amount == 8'd21 ? {i_in[20], {22{i_in[31]}}, i_in[30:21]} : + i_shift_amount == 8'd22 ? {i_in[21], {23{i_in[31]}}, i_in[30:22]} : + i_shift_amount == 8'd23 ? {i_in[22], {24{i_in[31]}}, i_in[30:23]} : + i_shift_amount == 8'd24 ? {i_in[23], {25{i_in[31]}}, i_in[30:24]} : + i_shift_amount == 8'd25 ? {i_in[24], {26{i_in[31]}}, i_in[30:25]} : + i_shift_amount == 8'd26 ? {i_in[25], {27{i_in[31]}}, i_in[30:26]} : + i_shift_amount == 8'd27 ? {i_in[26], {28{i_in[31]}}, i_in[30:27]} : + i_shift_amount == 8'd28 ? {i_in[27], {29{i_in[31]}}, i_in[30:28]} : + i_shift_amount == 8'd29 ? {i_in[28], {30{i_in[31]}}, i_in[30:29]} : + + i_shift_amount == 8'd30 ? {i_in[29], {31{i_in[31]}}, i_in[30 ]} : + i_shift_amount == 8'd31 ? {i_in[30], {32{i_in[31]}} } : + {i_in[31], {32{i_in[31]}} } ; // >= 32 + + + // carry out, < ------- out ---------> +assign ror_out = i_shift_imm_zero ? {i_in[ 0], i_carry_in, i_in[31: 1]} : // RXR, (ROR w/ imm 0) + + i_shift_amount[7:0] == 8'd 0 ? {i_carry_in, i_in } : // fall through case + + i_shift_amount[4:0] == 5'd 0 ? {i_in[31], i_in } : // Rs > 31 + i_shift_amount[4:0] == 5'd 1 ? {i_in[ 0], i_in[ 0], i_in[31: 1]} : + i_shift_amount[4:0] == 5'd 2 ? {i_in[ 1], i_in[ 1: 0], i_in[31: 2]} : + i_shift_amount[4:0] == 5'd 3 ? {i_in[ 2], i_in[ 2: 0], i_in[31: 3]} : + i_shift_amount[4:0] == 5'd 4 ? {i_in[ 3], i_in[ 3: 0], i_in[31: 4]} : + i_shift_amount[4:0] == 5'd 5 ? {i_in[ 4], i_in[ 4: 0], i_in[31: 5]} : + i_shift_amount[4:0] == 5'd 6 ? {i_in[ 5], i_in[ 5: 0], i_in[31: 6]} : + i_shift_amount[4:0] == 5'd 7 ? {i_in[ 6], i_in[ 6: 0], i_in[31: 7]} : + i_shift_amount[4:0] == 5'd 8 ? {i_in[ 7], i_in[ 7: 0], i_in[31: 8]} : + i_shift_amount[4:0] == 5'd 9 ? {i_in[ 8], i_in[ 8: 0], i_in[31: 9]} : + + i_shift_amount[4:0] == 5'd10 ? {i_in[ 9], i_in[ 9: 0], i_in[31:10]} : + i_shift_amount[4:0] == 5'd11 ? {i_in[10], i_in[10: 0], i_in[31:11]} : + i_shift_amount[4:0] == 5'd12 ? {i_in[11], i_in[11: 0], i_in[31:12]} : + i_shift_amount[4:0] == 5'd13 ? {i_in[12], i_in[12: 0], i_in[31:13]} : + i_shift_amount[4:0] == 5'd14 ? {i_in[13], i_in[13: 0], i_in[31:14]} : + i_shift_amount[4:0] == 5'd15 ? {i_in[14], i_in[14: 0], i_in[31:15]} : + i_shift_amount[4:0] == 5'd16 ? {i_in[15], i_in[15: 0], i_in[31:16]} : + i_shift_amount[4:0] == 5'd17 ? {i_in[16], i_in[16: 0], i_in[31:17]} : + i_shift_amount[4:0] == 5'd18 ? {i_in[17], i_in[17: 0], i_in[31:18]} : + i_shift_amount[4:0] == 5'd19 ? {i_in[18], i_in[18: 0], i_in[31:19]} : + + i_shift_amount[4:0] == 5'd20 ? {i_in[19], i_in[19: 0], i_in[31:20]} : + i_shift_amount[4:0] == 5'd21 ? {i_in[20], i_in[20: 0], i_in[31:21]} : + i_shift_amount[4:0] == 5'd22 ? {i_in[21], i_in[21: 0], i_in[31:22]} : + i_shift_amount[4:0] == 5'd23 ? {i_in[22], i_in[22: 0], i_in[31:23]} : + i_shift_amount[4:0] == 5'd24 ? {i_in[23], i_in[23: 0], i_in[31:24]} : + i_shift_amount[4:0] == 5'd25 ? {i_in[24], i_in[24: 0], i_in[31:25]} : + i_shift_amount[4:0] == 5'd26 ? {i_in[25], i_in[25: 0], i_in[31:26]} : + i_shift_amount[4:0] == 5'd27 ? {i_in[26], i_in[26: 0], i_in[31:27]} : + i_shift_amount[4:0] == 5'd28 ? {i_in[27], i_in[27: 0], i_in[31:28]} : + i_shift_amount[4:0] == 5'd29 ? {i_in[28], i_in[28: 0], i_in[31:29]} : + + i_shift_amount[4:0] == 5'd30 ? {i_in[29], i_in[29: 0], i_in[31:30]} : + {i_in[30], i_in[30: 0], i_in[31:31]} ; + + + +assign {o_carry_out, o_out} = i_function == LSL ? lsl_out : + i_function == LSR ? lsr_out : + i_function == ASR ? asr_out : + ror_out ; + +endmodule + + diff --git a/amber/a23_barrel_shift_fpga.v b/amber/a23_barrel_shift_fpga.v new file mode 100644 index 0000000..5aad589 --- /dev/null +++ b/amber/a23_barrel_shift_fpga.v @@ -0,0 +1,301 @@ +////////////////////////////////////////////////////////////////// +// // +// Barrel Shifter for Amber 2 Core // +// // +// The design is optimized for Altera family of FPGAs, // +// and it can be used directly or adapted other N-to-1 LUT // +// FPGA platforms. // +// // +// This file is part of the Amber project // +// http://www.opencores.org/project,amber // +// // +// Description // +// Provides 32-bit shifts LSL, LSR, ASR and ROR // +// // +// Author(s): // +// - Dmitry Tarnyagin, dmitry.tarnyagin@lockless.no // +// // +////////////////////////////////////////////////////////////////// +// // +// Copyright (C) 2010-2013 Authors and OPENCORES.ORG // +// // +// This source file may be used and distributed without // +// restriction provided that this copyright statement is not // +// removed from the file and that any derivative work contains // +// the original copyright notice and the associated disclaimer. // +// // +// This source file is free software; you can redistribute it // +// and/or modify it under the terms of the GNU Lesser General // +// Public License as published by the Free Software Foundation; // +// either version 2.1 of the License, or (at your option) any // +// later version. // +// // +// This source 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 Lesser General Public License for more // +// details. // +// // +// You should have received a copy of the GNU Lesser General // +// Public License along with this source; if not, download it // +// from http://www.opencores.org/lgpl.shtml // +// // +////////////////////////////////////////////////////////////////// + + +module a23_barrel_shift_fpga ( + +input [31:0] i_in, +input i_carry_in, +input [7:0] i_shift_amount, // uses 8 LSBs of Rs, or a 5 bit immediate constant +input i_shift_imm_zero, // high when immediate shift value of zero selected +input [1:0] i_function, + +output [31:0] o_out, +output o_carry_out + +); + +`include "a23_localparams.v" + +wire [31:0] rot_prod; // Input rotated by the shift amount + +wire [1:0] lsl_out; // LSL: {carry, bit_31} +wire [1:0] lsr_out; // LSR: {carry, bit_31} +wire [1:0] asr_out; // ASR: {carry, bit_31} +wire [1:0] ror_out; // ROR: {carry, bit_31} + +reg [32:0] lsl_mask; // Left-hand mask +reg [32:0] lsr_mask; // Right-hand mask +reg [15:0] low_mask; // Mask calculation helper + +reg [4:0] shift_amount; // Shift amount for the low-level shifter + +reg [2:0] lsl_selector; // Left shift {shift_32, shift_over, shift_amount[4]} +reg [2:0] lsr_selector; // Right shift {shift_32, shift_over, shift_amount[4]} +reg [3:0] low_selector; // {shift_amount[3:0]} + +reg shift_nzero; // Amount is not zero +reg shift_over; // Amount is 32 or higher +reg shift_32; // Amount is exactly 32 +reg asr_sign; // Sign for ASR shift +reg direction; // Shift direction + +wire [31:0] p_r; // 1 bit rotated rot_prod +wire [31:0] p_l; // Alias for the rot_prod + + +// Implementation details: +// Design is based on masking of rotated input by a left- and right- hand masks. +// Rotated product calculation requires 5 levels of combinational logic, and masks +// must be ready before the product is ready. In fact masks require just 3 to 4 levels +// of logic cells using 4-to-1/2x3-to-1 Altera. + +always @* +begin + shift_32 = i_shift_amount == 32; + + shift_over = |i_shift_amount[7:5]; + + shift_nzero = |i_shift_amount[7:0]; + + shift_amount = i_shift_amount[4:0]; + + if (i_shift_imm_zero) begin + if (i_function == LSR || i_function == ASR) begin + // The form of the shift field which might be + // expected to correspond to LSR #0 is used + // to encode LSR #32, which has a zero result + // with bit 31 of Rm as the carry output. + shift_nzero = 1'b1; + shift_over = 1'b1; + // Redundant and can be optimized out + // shift_32 = 1'b1; + end else if (i_function == ROR) begin + // RXR, (ROR w/ imm 0) + shift_amount[0] = 1'b1; + shift_nzero = 1'b1; + end + end + + // LSB sub-selector calculation. Usually it is taken + // directly from the shift_amount, but ROR requires + // no masking at all. + case (i_function) + LSL: low_selector = shift_amount[3:0]; + LSR: low_selector = shift_amount[3:0]; + ASR: low_selector = shift_amount[3:0]; + ROR: low_selector = 4'b0000; + endcase + + // Left-hand MSB sub-selector calculation. Opaque for every function but LSL. + case (i_function) + LSL: lsl_selector = {shift_32, shift_over, shift_amount[4]}; + LSR: lsl_selector = 3'b0_1_0; // Opaque mask selector + ASR: lsl_selector = 3'b0_1_0; // Opaque mask selector + ROR: lsl_selector = 3'b0_1_0; // Opaque mask selector + endcase + + // Right-hand MSB sub-selector calculation. Opaque for LSL, transparent for ROR. + case (i_function) + LSL: lsr_selector = 3'b0_1_0; // Opaque mask selector + LSR: lsr_selector = {shift_32, shift_over, shift_amount[4]}; + ASR: lsr_selector = {shift_32, shift_over, shift_amount[4]}; + ROR: lsr_selector = 3'b0_0_0; // Transparent mask selector + endcase + + // Direction + case (i_function) + LSL: direction = 1'b0; // Left shift + LSR: direction = 1'b1; // Right shift + ASR: direction = 1'b1; // Right shift + ROR: direction = 1'b1; // Right shift + endcase + + // Sign for ASR shift + asr_sign = 1'b0; + if (i_function == ASR && i_in[31]) + asr_sign = 1'b1; +end + +// Generic rotate. Theoretical cost: 32x5 4-to-1 LUTs. +// Practically a bit higher due to high fanout of "direction". +generate +genvar i, j; + for (i = 0; i < 5; i = i + 1) + begin : netgen + wire [31:0] in; + reg [31:0] out; + for (j = 0; j < 32; j = j + 1) + begin : net + always @* + out[j] = in[j] & (~shift_amount[i] ^ direction) | + in[wrap(j, i)] & (shift_amount[i] ^ direction); + end + end + + // Order is reverted with respect to volatile shift_amount[0] + assign netgen[4].in = i_in; + for (i = 1; i < 5; i = i + 1) + begin : router + assign netgen[i-1].in = netgen[i].out; + end +endgenerate + +// Aliasing +assign rot_prod = netgen[0].out; + +// Submask calculated from LSB sub-selector. +// Cost: 16 4-to-1 LUTs. +always @* +case (low_selector) // synthesis full_case parallel_case + 4'b0000: low_mask = 16'hffff; + 4'b0001: low_mask = 16'hfffe; + 4'b0010: low_mask = 16'hfffc; + 4'b0011: low_mask = 16'hfff8; + 4'b0100: low_mask = 16'hfff0; + 4'b0101: low_mask = 16'hffe0; + 4'b0110: low_mask = 16'hffc0; + 4'b0111: low_mask = 16'hff80; + 4'b1000: low_mask = 16'hff00; + 4'b1001: low_mask = 16'hfe00; + 4'b1010: low_mask = 16'hfc00; + 4'b1011: low_mask = 16'hf800; + 4'b1100: low_mask = 16'hf000; + 4'b1101: low_mask = 16'he000; + 4'b1110: low_mask = 16'hc000; + 4'b1111: low_mask = 16'h8000; +endcase + +// Left-hand mask calculation. +// Cost: 33 4-to-1 LUTs. +always @* +casez (lsl_selector) // synthesis full_case parallel_case + 7'b1??: lsl_mask = 33'h_1_0000_0000; + 7'b01?: lsl_mask = 33'h_0_0000_0000; + 7'b001: lsl_mask = { 1'h_1, low_mask, 16'h_0000}; + 7'b000: lsl_mask = {17'h_1_ffff, low_mask}; +endcase + +// Right-hand mask calculation. +// Cost: 33 4-to-1 LUTs. +always @* +casez (lsr_selector) // synthesis full_case parallel_case + 7'b1??: lsr_mask = 33'h_1_0000_0000; + 7'b01?: lsr_mask = 33'h_0_0000_0000; + 7'b000: lsr_mask = { 1'h_1, bit_swap(low_mask), 16'h_ffff}; + 7'b001: lsr_mask = {17'h_1_0000, bit_swap(low_mask)}; +endcase + +// Alias: right-rotated +assign p_r = {rot_prod[30:0], rot_prod[31]}; + +// Alias: left-rotated +assign p_l = rot_prod[31:0]; + +// ROR MSB, handling special cases +assign ror_out[0] = i_shift_imm_zero ? i_carry_in : + p_r[31]; + +// ROR carry, handling special cases +assign ror_out[1] = i_shift_imm_zero ? i_in[0] : + shift_nzero ? p_r[31] : + i_carry_in; + +// LSL MSB +assign lsl_out[0] = p_l[31] & lsl_mask[31]; + +// LSL carry, handling special cases +assign lsl_out[1] = shift_nzero ? p_l[0] & lsl_mask[32]: + i_carry_in; + +// LSR MSB +assign lsr_out[0] = p_r[31] & lsr_mask[31]; + +// LSR carry, handling special cases +assign lsr_out[1] = i_shift_imm_zero ? i_in[31] : + shift_nzero ? p_r[31] & lsr_mask[32]: + i_carry_in; + +// ASR MSB +assign asr_out[0] = i_in[31] ? i_in[31] : + p_r[31] & lsr_mask[31] ; + +// LSR carry, handling special cases +assign asr_out[1] = shift_over ? i_in[31] : + shift_nzero ? p_r[31] : + i_carry_in; + +// Carry and MSB are calculated as above +assign {o_carry_out, o_out[31]} = i_function == LSL ? lsl_out : + i_function == LSR ? lsr_out : + i_function == ASR ? asr_out : + ror_out ; + +// And the rest of result is the masked rotated input. +assign o_out[30:0] = (p_l[30:0] & lsl_mask[30:0]) | + (p_r[30:0] & lsr_mask[30:0]) | + (~lsr_mask[30:0] & {31{asr_sign}}); + +// Rotate: calculate bit pos for level "level" and offset "pos" +function [4:0] wrap; +input integer pos; +input integer level; +integer out; +begin + out = pos - (1 << level); + wrap = out[4:0]; +end +endfunction + +// Swap bits in the input 16-bit value +function [15:0] bit_swap; +input [15:0] value; +integer i; +begin + for (i = 0; i < 16; i = i + 1) + bit_swap[i] = value[15 - i]; +end +endfunction + +endmodule diff --git a/amber/a23_cache.v b/amber/a23_cache.v new file mode 100644 index 0000000..d61b51b --- /dev/null +++ b/amber/a23_cache.v @@ -0,0 +1,891 @@ +////////////////////////////////////////////////////////////////// +// // +// L1 Cache for Amber 2 Core // +// // +// This file is part of the Amber project // +// http://www.opencores.org/project,amber // +// // +// Description // +// Synthesizable L1 Unified Data and Instruction Cache // +// Cache is 4-way, 256 line and 16 bytes per line for // +// a total of 16KB. The cache policy is write-through and // +// read allocate. For swap instructions (SWP and SWPB) the // +// location is evicted from the cache and read from main // +// memory. // +// // +// Author(s): // +// - Conor Santifort, csantifort.amber@gmail.com // +// // +////////////////////////////////////////////////////////////////// +// // +// Copyright (C) 2010 Authors and OPENCORES.ORG // +// // +// This source file may be used and distributed without // +// restriction provided that this copyright statement is not // +// removed from the file and that any derivative work contains // +// the original copyright notice and the associated disclaimer. // +// // +// This source file is free software; you can redistribute it // +// and/or modify it under the terms of the GNU Lesser General // +// Public License as published by the Free Software Foundation; // +// either version 2.1 of the License, or (at your option) any // +// later version. // +// // +// This source 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 Lesser General Public License for more // +// details. // +// // +// You should have received a copy of the GNU Lesser General // +// Public License along with this source; if not, download it // +// from http://www.opencores.org/lgpl.shtml // +// // +////////////////////////////////////////////////////////////////// + +`include "a23_config_defines.v" + +module a23_cache +#( + +// --------------------------------------------------------- +// Cache Configuration + +// Limited to Linux 4k page sizes -> 256 lines +parameter CACHE_LINES = 256, + +// This cannot be changed without some major surgeory on +// this module +parameter CACHE_WORDS_PER_LINE = 4, + +// Changing this parameter is the recommended +// way to change the overall cache size; 2, 4 and 8 ways are supported. +// 2 ways -> 8KB cache +// 4 ways -> 16KB cache +// 8 ways -> 32KB cache +parameter WAYS = `A23_CACHE_WAYS , + +// derived configuration parameters +parameter CACHE_ADDR_WIDTH = log2 ( CACHE_LINES ), // = 8 +parameter WORD_SEL_WIDTH = log2 ( CACHE_WORDS_PER_LINE ), // = 2 +parameter TAG_ADDR_WIDTH = 32 - CACHE_ADDR_WIDTH - WORD_SEL_WIDTH - 2, // = 20 +parameter TAG_WIDTH = TAG_ADDR_WIDTH + 1, // = 21, including Valid flag +parameter CACHE_LINE_WIDTH = CACHE_WORDS_PER_LINE * 32, // = 128 +parameter TAG_ADDR32_LSB = CACHE_ADDR_WIDTH + WORD_SEL_WIDTH + 2, // = 12 +parameter CACHE_ADDR32_MSB = CACHE_ADDR_WIDTH + WORD_SEL_WIDTH + 2 - 1, // = 11 +parameter CACHE_ADDR32_LSB = WORD_SEL_WIDTH + 2 , // = 4 +parameter WORD_SEL_MSB = WORD_SEL_WIDTH + 2 - 1, // = 3 +parameter WORD_SEL_LSB = 2 // = 2 +// --------------------------------------------------------- +) + + +( +input i_clk, + +// Read / Write requests from core +input i_select, +input i_exclusive, // exclusive access, part of swap instruction +input [31:0] i_write_data, +input i_write_enable, // core issued write request +input [31:0] i_address, // registered address from execute +input [31:0] i_address_nxt, // un-registered version of address from execute stage +input [3:0] i_byte_enable, +input i_cache_enable, // from co-processor 15 configuration register +input i_cache_flush, // from co-processor 15 register + +output [31:0] o_read_data, +input i_core_stall, +output o_stall, + +// WB Read Request +output o_wb_req, // Read Request +input [31:0] i_wb_address, // wb bus +input [31:0] i_wb_read_data, // wb bus +input i_wb_stall // wb_stb && !wb_ack +); + +`include "a23_localparams.v" +`include "a23_functions.v" + +// One-hot encoded +localparam C_INIT = 0, + C_CORE = 1, + C_FILL = 2, + C_INVA = 3, + C_STATES = 4; + +localparam [3:0] CS_INIT = 4'd0, + CS_IDLE = 4'd1, + CS_FILL1 = 4'd2, + CS_FILL2 = 4'd3, + CS_FILL3 = 4'd4, + CS_FILL4 = 4'd5, + CS_FILL_COMPLETE = 4'd6, + CS_TURN_AROUND = 4'd7, + CS_WRITE_HIT1 = 4'd8, + CS_EX_DELETE = 4'd9; + + +reg [3:0] c_state = CS_IDLE; +reg [C_STATES-1:0] source_sel = 1'd1 << C_CORE; +reg [CACHE_ADDR_WIDTH:0] init_count = 'd0; + +wire [TAG_WIDTH-1:0] tag_rdata_way [WAYS-1:0]; +wire [CACHE_LINE_WIDTH-1:0] data_rdata_way[WAYS-1:0]; +wire [WAYS-1:0] data_wenable_way; +wire [WAYS-1:0] data_hit_way; +wire [WAYS-1:0] tag_wenable_way; +reg [WAYS-1:0] select_way = 'd0; +wire [WAYS-1:0] next_way; +reg [WAYS-1:0] valid_bits_r = 'd0; + +reg [3:0] random_num = 4'hf; + +wire [CACHE_ADDR_WIDTH-1:0] tag_address; +wire [TAG_WIDTH-1:0] tag_wdata; +wire tag_wenable; + +wire [CACHE_LINE_WIDTH-1:0] read_miss_wdata; +wire [CACHE_LINE_WIDTH-1:0] write_hit_wdata; +wire [CACHE_LINE_WIDTH-1:0] data_wdata; +wire [CACHE_ADDR_WIDTH-1:0] data_address; +wire [31:0] write_data_word; + +wire hit; +wire read_miss; +wire write_miss; +wire write_hit; + +reg [31:0] miss_address = 'd0; +wire [CACHE_LINE_WIDTH-1:0] hit_rdata; + +wire write_stall; +wire cache_busy_stall; +wire read_stall; + +wire enable; +wire [CACHE_ADDR_WIDTH-1:0] address; + +reg [CACHE_LINE_WIDTH-1:0] wb_rdata_burst = 'd0; +reg wb_read_buf_valid = 'd0; +reg [31:0] wb_read_buf_address = 'd0; +reg [31:0] wb_read_buf_data = 'd0; +wire wb_read_buf_hit; + +wire exclusive_access; +wire ex_read_hit; +reg ex_read_hit_r = 'd0; +reg [WAYS-1:0] ex_read_hit_way = 'd0; +reg [CACHE_ADDR_WIDTH-1:0] ex_read_address; +wire ex_read_hit_clear; +wire ex_read_cache_busy; + +genvar i; + +// ====================================== +// Address to use for cache access +// ====================================== +// If currently stalled then the address for the next +// cycle will be the same as it is in the current cycle +// +assign address = i_core_stall ? i_address [CACHE_ADDR32_MSB:CACHE_ADDR32_LSB] : + i_address_nxt[CACHE_ADDR32_MSB:CACHE_ADDR32_LSB] ; + +// ====================================== +// Outputs +// ====================================== +assign o_read_data = wb_read_buf_hit ? wb_read_buf_data : + i_address[WORD_SEL_MSB:WORD_SEL_LSB] == 2'd0 ? hit_rdata [31:0] : + i_address[WORD_SEL_MSB:WORD_SEL_LSB] == 2'd1 ? hit_rdata [63:32] : + i_address[WORD_SEL_MSB:WORD_SEL_LSB] == 2'd2 ? hit_rdata [95:64] : + hit_rdata [127:96] ; + +// Don't allow the cache to stall the wb i/f for an exclusive access +// The cache needs a couple of cycles to flush a potential copy of the exclusive +// address, but the wb can do the access in parallel. So there is no +// stall in the state CS_EX_DELETE, even though the cache is out of action. +// This works fine as long as the wb is stalling the core +assign o_stall = read_stall || write_stall || cache_busy_stall || ex_read_cache_busy; + +assign o_wb_req = (( read_miss || write_miss ) && c_state == CS_IDLE ) || + c_state == CS_WRITE_HIT1; +initial begin + + c_state = CS_IDLE; + +end + +// ====================================== +// Cache State Machine +// ====================================== + +// Little State Machine to Flush Tag RAMS +always @ ( posedge i_clk ) + if ( i_cache_flush ) + begin + c_state <= CS_INIT; + source_sel <= 1'd1 << C_INIT; + init_count <= 'd0; + `ifdef A23_CACHE_DEBUG + `TB_DEBUG_MESSAGE + $display("Cache Flush"); + `endif + end + else + case ( c_state ) + CS_INIT : + if ( init_count < CACHE_LINES [CACHE_ADDR_WIDTH:0] ) + begin + init_count <= init_count + 1'd1; + source_sel <= 1'd1 << C_INIT; + end + else + begin + source_sel <= 1'd1 << C_CORE; + c_state <= CS_TURN_AROUND; + end + + CS_IDLE : + begin + source_sel <= 1'd1 << C_CORE; + + if ( ex_read_hit || ex_read_hit_r ) + begin + select_way <= data_hit_way | ex_read_hit_way; + c_state <= CS_EX_DELETE; + source_sel <= 1'd1 << C_INVA; + end + else if ( read_miss ) + begin + // wb read request asserted, wait for ack + if ( !i_wb_stall ) + c_state <= CS_FILL1; + end + else if ( write_hit ) + c_state <= CS_WRITE_HIT1; + end + + + CS_FILL1 : + begin + // wb read request asserted, wait for ack + if ( !i_wb_stall ) + c_state <= CS_FILL2; + end + + + CS_FILL2 : + // first read of burst of 4 + // wb read request asserted, wait for ack + if ( !i_wb_stall ) + c_state <= CS_FILL3; + + + CS_FILL3 : + // second read of burst of 4 + // wb read request asserted, wait for ack + if ( !i_wb_stall ) + c_state <= CS_FILL4; + + + CS_FILL4 : + // third read of burst of 4 + // wb read request asserted, wait for ack + if ( !i_wb_stall ) + begin + c_state <= CS_FILL_COMPLETE; + source_sel <= 1'd1 << C_FILL; + + // Pick a way to write the cache update into + // Either pick one of the invalid caches, or if all are valid, then pick + // one randomly + + select_way <= next_way; + random_num <= {random_num[2], random_num[1], random_num[0], + random_num[3]^random_num[2]}; + end + + + // Write the read fetch data in this cycle + CS_FILL_COMPLETE : + // fourth read of burst of 4 + // wb read request asserted, wait for ack + if ( !i_wb_stall ) + begin + // Back to normal cache operations, but + // use physical address for first read as + // address moved before the stall was asserted for the read_miss + // However don't use it if its a non-cached address! + source_sel <= 1'd1 << C_CORE; + c_state <= CS_TURN_AROUND; + end + + + // Ignore the tag read data in this cycle + // Wait 1 cycle to pre-read the cache and return to normal operation + CS_TURN_AROUND : + begin + c_state <= CS_IDLE; + end + + + // Flush the entry matching an exclusive access + CS_EX_DELETE: + begin + `ifdef A23_CACHE_DEBUG + `TB_DEBUG_MESSAGE + $display("Cache deleted Locked entry"); + `endif + c_state <= CS_TURN_AROUND; + source_sel <= 1'd1 << C_CORE; + end + + + CS_WRITE_HIT1: + begin + // wait for an ack on the wb bus to complete the write + if ( !i_wb_stall ) + c_state <= CS_IDLE; + + end + endcase + + +// ====================================== +// Capture WB Block Read - burst of 4 words +// ====================================== +always @ ( posedge i_clk ) + if ( !i_wb_stall ) + wb_rdata_burst <= {i_wb_read_data, wb_rdata_burst[127:32]}; + + +// ====================================== +// WB Read Buffer +// ====================================== +always @ ( posedge i_clk ) + begin + if ( c_state == CS_FILL1 || c_state == CS_FILL2 || + c_state == CS_FILL3 || c_state == CS_FILL4 ) + begin + if ( !i_wb_stall ) + begin + wb_read_buf_valid <= 1'd1; + wb_read_buf_address <= i_wb_address; + wb_read_buf_data <= i_wb_read_data; + end + end + else + wb_read_buf_valid <= 1'd0; + end + + +// ====================================== +// Miss Address +// ====================================== +always @ ( posedge i_clk ) + if ( o_wb_req ) + miss_address <= i_address; + + +// ====================================== +// Remember Read-Modify-Write Hit +// ====================================== +assign ex_read_hit_clear = c_state == CS_EX_DELETE; + +always @ ( posedge i_clk ) + if ( ex_read_hit_clear ) + begin + ex_read_hit_r <= 1'd0; + ex_read_hit_way <= 'd0; + end + else if ( ex_read_hit ) + begin + + `ifdef A23_CACHE_DEBUG + `TB_DEBUG_MESSAGE + $display ("Exclusive access cache hit address 0x%08h", i_address); + `endif + + ex_read_hit_r <= 1'd1; + ex_read_hit_way <= data_hit_way; + end + else if ( c_state == CS_FILL_COMPLETE && ex_read_hit_r ) + ex_read_hit_way <= select_way; + + +always @ (posedge i_clk) + if ( ex_read_hit ) + ex_read_address <= i_address[CACHE_ADDR32_MSB:CACHE_ADDR32_LSB]; + + +assign tag_address = source_sel[C_FILL] ? miss_address [CACHE_ADDR32_MSB:CACHE_ADDR32_LSB] : + source_sel[C_INVA] ? ex_read_address : + source_sel[C_INIT] ? init_count[CACHE_ADDR_WIDTH-1:0] : + source_sel[C_CORE] ? address : + {CACHE_ADDR_WIDTH{1'd0}} ; + + +assign data_address = write_hit ? i_address [CACHE_ADDR32_MSB:CACHE_ADDR32_LSB] : + source_sel[C_FILL] ? miss_address[CACHE_ADDR32_MSB:CACHE_ADDR32_LSB] : + source_sel[C_CORE] ? address : + {CACHE_ADDR_WIDTH{1'd0}} ; + + +assign tag_wdata = source_sel[C_FILL] ? {1'd1, miss_address[31:TAG_ADDR32_LSB]} : + {TAG_WIDTH{1'd0}} ; + + + // Data comes in off the WB bus in wrap4 with the missed data word first +assign data_wdata = write_hit && c_state == CS_IDLE ? write_hit_wdata : read_miss_wdata; + +assign read_miss_wdata = miss_address[3:2] == 2'd0 ? wb_rdata_burst : + miss_address[3:2] == 2'd1 ? { wb_rdata_burst[95:0], wb_rdata_burst[127:96] }: + miss_address[3:2] == 2'd2 ? { wb_rdata_burst[63:0], wb_rdata_burst[127:64] }: + { wb_rdata_burst[31:0], wb_rdata_burst[127:32] }; + + +assign write_hit_wdata = i_address[3:2] == 2'd0 ? {hit_rdata[127:32], write_data_word } : + i_address[3:2] == 2'd1 ? {hit_rdata[127:64], write_data_word, hit_rdata[31:0] } : + i_address[3:2] == 2'd2 ? {hit_rdata[127:96], write_data_word, hit_rdata[63:0] } : + { write_data_word, hit_rdata[95:0] } ; + +// Use Byte Enables +assign write_data_word = i_byte_enable == 4'b0001 ? { o_read_data[31: 8], i_write_data[ 7: 0] } : + i_byte_enable == 4'b0010 ? { o_read_data[31:16], i_write_data[15: 8], o_read_data[ 7:0]} : + i_byte_enable == 4'b0100 ? { o_read_data[31:24], i_write_data[23:16], o_read_data[15:0]} : + i_byte_enable == 4'b1000 ? { i_write_data[31:24], o_read_data[23:0]} : + i_byte_enable == 4'b0011 ? { o_read_data[31:16], i_write_data[15: 0] } : + i_byte_enable == 4'b1100 ? { i_write_data[31:16], o_read_data[15:0]} : + i_write_data ; + + +assign tag_wenable = source_sel[C_INVA] ? 1'd1 : + source_sel[C_FILL] ? 1'd1 : + source_sel[C_INIT] ? 1'd1 : + source_sel[C_CORE] ? 1'd0 : + 1'd0 ; + + +assign enable = i_select && i_cache_enable; + +assign exclusive_access = i_exclusive && i_cache_enable; + + + // the wb read buffer returns data directly from the wb bus to the + // core during a read miss operation +assign wb_read_buf_hit = enable && wb_read_buf_address == i_address && wb_read_buf_valid; + +assign hit = |data_hit_way; + +assign write_hit = enable && i_write_enable && hit; + +assign write_miss = enable && i_write_enable && !hit && c_state != CS_WRITE_HIT1; + +assign read_miss = enable && !i_write_enable && !(hit || wb_read_buf_hit); + + // Exclusive read hit +assign ex_read_hit = exclusive_access && !i_write_enable && (hit || wb_read_buf_hit); + + // Added to fix rare swap bug which occurs when the cache starts + // a fill just as the swap instruction starts to execute. The cache + // fails to check for a read hit on the swap read cycle. + // This signal stalls the core in that case until after the + // fill has completed. +assign ex_read_cache_busy = exclusive_access && !i_write_enable && c_state != CS_IDLE; + + // Need to stall for a write miss to wait for the current wb + // read miss access to complete. Also for a write hit, need + // to stall for 1 cycle while the data cache is being written to +assign write_stall = ( write_hit && c_state != CS_WRITE_HIT1 ) || + ( write_miss && ( c_state != CS_IDLE ) ) || + i_wb_stall ; + +assign read_stall = read_miss; + + // Core may or may not be trying to access cache memory during + // this phase of the read fetch. It could be doing e.g. a wb access +assign cache_busy_stall = ((c_state == CS_TURN_AROUND || c_state == CS_FILL1) && enable) || + c_state == CS_INIT; + + +// ====================================== +// Instantiate RAMS +// ====================================== + +generate + for ( i=0; i 4'd1 ) + begin + //`TB_ERROR_MESSAGE + $display("Hit in more than one cache ways!"); + end + +end +else if ( WAYS == 3 ) begin : check_hit_3ways + + always @( posedge i_clk ) + if ( (data_hit_way[0] + data_hit_way[1] + data_hit_way[2] ) > 4'd1 ) + begin + //`TB_ERROR_MESSAGE + $display("Hit in more than one cache ways!"); + end + +end +else if ( WAYS == 4 ) begin : check_hit_4ways + + always @( posedge i_clk ) + if ( (data_hit_way[0] + data_hit_way[1] + + data_hit_way[2] + data_hit_way[3] ) > 4'd1 ) + begin + //`TB_ERROR_MESSAGE + $display("Hit in more than one cache ways!"); + end + +end +else if ( WAYS == 8 ) begin : check_hit_8ways + + always @( posedge i_clk ) + if ( (data_hit_way[0] + data_hit_way[1] + + data_hit_way[2] + data_hit_way[3] + + data_hit_way[4] + data_hit_way[5] + + data_hit_way[6] + data_hit_way[7] ) > 4'd1 ) + begin + //`TB_ERROR_MESSAGE + $display("Hit in more than one cache ways!"); + end + +end +else begin : check_hit_nways + + initial + begin + //`TB_ERROR_MESSAGE + $display("Unsupported number of ways %0d", WAYS); + $display("Set A23_CACHE_WAYS in a23_config_defines.v to either 2,3,4 or 8"); + end + +end +endgenerate + +//synopsys translate_on + +endmodule + diff --git a/amber/a23_config_defines.v b/amber/a23_config_defines.v new file mode 100644 index 0000000..c7f168c --- /dev/null +++ b/amber/a23_config_defines.v @@ -0,0 +1,81 @@ +////////////////////////////////////////////////////////////////// +// // +// Amber Configuration and Debug for the AMber 2 Core // +// // +// This file is part of the Amber project // +// http://www.opencores.org/project,amber // +// // +// Description // +// Contains a set of defines used to configure and debug // +// the Amber core // +// // +// Author(s): // +// - Conor Santifort, csantifort.amber@gmail.com // +// // +////////////////////////////////////////////////////////////////// +// // +// Copyright (C) 2010 Authors and OPENCORES.ORG // +// // +// This source file may be used and distributed without // +// restriction provided that this copyright statement is not // +// removed from the file and that any derivative work contains // +// the original copyright notice and the associated disclaimer. // +// // +// This source file is free software; you can redistribute it // +// and/or modify it under the terms of the GNU Lesser General // +// Public License as published by the Free Software Foundation; // +// either version 2.1 of the License, or (at your option) any // +// later version. // +// // +// This source 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 Lesser General Public License for more // +// details. // +// // +// You should have received a copy of the GNU Lesser General // +// Public License along with this source; if not, download it // +// from http://www.opencores.org/lgpl.shtml // +// // +////////////////////////////////////////////////////////////////// + +`ifndef _A23_CONFIG_DEFINES +`define _A23_CONFIG_DEFINES + +// Cache Ways +// Changing this parameter is the recommended +// way to change the Amber cache size; 2, 3, 4 and 8 ways are supported. +// 2 ways -> 8KB cache +// 3 ways -> 12KB cache +// 4 ways -> 16KB cache +// 8 ways -> 32KB cache +`define A23_CACHE_WAYS 4 + +// Use ram-based register bank implementation +// `define A23_RAM_REGISTER_BANK + +// -------------------------------------------------------------------- +// Debug switches +// -------------------------------------------------------------------- + +// Enable the decompiler. The default output file is amber.dis +//`define A23_DECOMPILE + +// Co-processor 15 debug. Registers in here control the cache +//`define A23_COPRO15_DEBUG + +// Cache debug +//`define A23_CACHE_DEBUG + +// -------------------------------------------------------------------- + + +// -------------------------------------------------------------------- +// File Names +// -------------------------------------------------------------------- +`ifndef A23_DECOMPILE_FILE + `define A23_DECOMPILE_FILE "amber.dis" +`endif + +`endif + diff --git a/amber/a23_coprocessor.v b/amber/a23_coprocessor.v new file mode 100644 index 0000000..39d434d --- /dev/null +++ b/amber/a23_coprocessor.v @@ -0,0 +1,197 @@ +////////////////////////////////////////////////////////////////// +// // +// Co-processor module for Amber 2 Core // +// // +// This file is part of the Amber project // +// http://www.opencores.org/project,amber // +// // +// Description // +// Co_processor 15 registers and control signals // // +// Author(s): // +// - Conor Santifort, csantifort.amber@gmail.com // +// // +////////////////////////////////////////////////////////////////// +// // +// Copyright (C) 2010 Authors and OPENCORES.ORG // +// // +// This source file may be used and distributed without // +// restriction provided that this copyright statement is not // +// removed from the file and that any derivative work contains // +// the original copyright notice and the associated disclaimer. // +// // +// This source file is free software; you can redistribute it // +// and/or modify it under the terms of the GNU Lesser General // +// Public License as published by the Free Software Foundation; // +// either version 2.1 of the License, or (at your option) any // +// later version. // +// // +// This source 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 Lesser General Public License for more // +// details. // +// // +// You should have received a copy of the GNU Lesser General // +// Public License along with this source; if not, download it // +// from http://www.opencores.org/lgpl.shtml // +// // +////////////////////////////////////////////////////////////////// + + +module a23_coprocessor +( +input i_clk, +input i_fetch_stall, // stall all stages of the cpu at the same time +input [2:0] i_copro_opcode1, +input [2:0] i_copro_opcode2, +input [3:0] i_copro_crn, // Register Number +input [3:0] i_copro_crm, +input [3:0] i_copro_num, +input [1:0] i_copro_operation, +input [31:0] i_copro_write_data, + +input i_fault, // high to latch the fault address and status +input [7:0] i_fault_status, +input [31:0] i_fault_address, // the address that caused the fault + +output reg [31:0] o_copro_read_data, +output o_cache_enable, +output o_cache_flush, +output [31:0] o_cacheable_area +); + +// Bit 0 - Cache on(1)/off +// Bit 1 - Shared (1) or seperate User/Supervisor address space +// Bit 2 - address monitor mode(1) +reg [2:0] cache_control = 3'b000; + +// Bit 0 - 2MB memory from 0 to 0x01fffff cacheable(1)/not cachable +// Bit 1 - next 2MB region etc. +reg [31:0] cacheable_area = 32'h0; + +// Marks memory regions as read only so writes are ignored by the cache +// Bit 0 - 2MB memory from 0 to 0x01fffff updateable(1)/not updateable +// Bit 1 - next 2MB region etc. +reg [31:0] updateable_area = 32'h0; + +// Accesses to a region with a flag set in this register cause the +// cache to flush +// Bit 0 - 2MB memory from 0 to 0x01fffff +// Bit 1 - next 2MB region etc. +reg [31:0] disruptive_area = 32'h0; + + +reg [7:0] fault_status = 'd0; +reg [31:0] fault_address = 'd0; // the address that caused the fault + +wire copro15_reg1_write; + + +// --------------------------- +// Outputs +// --------------------------- +assign o_cache_enable = cache_control[0]; +assign o_cache_flush = copro15_reg1_write; +assign o_cacheable_area = cacheable_area; + +// --------------------------- +// Capture an access fault address and status +// --------------------------- +always @ ( posedge i_clk ) + if ( !i_fetch_stall ) + begin + if ( i_fault ) + begin + + `ifdef A23_COPRO15_DEBUG + $display ("Fault status set to 0x%08x", i_fault_status); + $display ("Fault address set to 0x%08x", i_fault_address); + `endif + fault_status <= i_fault_status; + fault_address <= i_fault_address; + end + end + + +// --------------------------- +// Register Writes +// --------------------------- +always @ ( posedge i_clk ) + if ( !i_fetch_stall ) + begin + if ( i_copro_operation == 2'd2 ) + case ( i_copro_crn ) + 4'd2: cache_control <= i_copro_write_data[2:0]; + 4'd3: cacheable_area <= i_copro_write_data[31:0]; + 4'd4: updateable_area <= i_copro_write_data[31:0]; + 4'd5: disruptive_area <= i_copro_write_data[31:0]; + endcase + end + +// Flush the cache +assign copro15_reg1_write = !i_fetch_stall && i_copro_operation == 2'd2 && i_copro_crn == 4'd1; + + +// --------------------------- +// Register Reads +// --------------------------- +always @ ( posedge i_clk ) + if ( !i_fetch_stall ) + case ( i_copro_crn ) + // ID Register - [31:24] Company id, [23:16] Manuf id, [15:8] Part type, [7:0] revision + 4'd0: o_copro_read_data <= 32'h4156_0300; + 4'd2: o_copro_read_data <= {29'd0, cache_control}; + 4'd3: o_copro_read_data <= cacheable_area; + 4'd4: o_copro_read_data <= updateable_area; + 4'd5: o_copro_read_data <= disruptive_area; + 4'd6: o_copro_read_data <= {24'd0, fault_status }; + 4'd7: o_copro_read_data <= fault_address; + default: o_copro_read_data <= 32'd0; + endcase + + + +// ======================================================== +// Debug code - not synthesizable +// ======================================================== + +`ifdef A23_COPRO15_DEBUG +//synopsys translate_off +reg [1:0] copro_operation_d1; +reg [3:0] copro_crn_d1; + +always @( posedge i_clk ) + if ( !i_fetch_stall ) + begin + copro_operation_d1 <= i_copro_operation; + copro_crn_d1 <= i_copro_crn; + end + +always @( posedge i_clk ) + if ( !i_fetch_stall ) + begin + if ( i_copro_operation == 2'd2 ) // mcr + case ( i_copro_crn ) + 4'd 1: begin `TB_DEBUG_MESSAGE $display ("Write 0x%08h to Co-Pro 15 #1, Flush Cache", i_copro_write_data); end + 4'd 2: begin `TB_DEBUG_MESSAGE $display ("Write 0x%08h to Co-Pro 15 #2, Cache Control", i_copro_write_data); end + 4'd 3: begin `TB_DEBUG_MESSAGE $display ("Write 0x%08h to Co-Pro 15 #3, Cacheable area", i_copro_write_data); end + 4'd 4: begin `TB_DEBUG_MESSAGE $display ("Write 0x%08h to Co-Pro 15 #4, Updateable area", i_copro_write_data); end + 4'd 5: begin `TB_DEBUG_MESSAGE $display ("Write 0x%08h to Co-Pro 15 #5, Disruptive area", i_copro_write_data); end + endcase + + if ( copro_operation_d1 == 2'd1 ) // mrc + case ( copro_crn_d1 ) + 4'd 0: begin `TB_DEBUG_MESSAGE $display ("Read 0x%08h from Co-Pro 15 #0, ID Register", o_copro_read_data); end + 4'd 2: begin `TB_DEBUG_MESSAGE $display ("Read 0x%08h from Co-Pro 15 #2, Cache control", o_copro_read_data); end + 4'd 3: begin `TB_DEBUG_MESSAGE $display ("Read 0x%08h from Co-Pro 15 #3, Cacheable area", o_copro_read_data); end + 4'd 4: begin `TB_DEBUG_MESSAGE $display ("Read 0x%08h from Co-Pro 15 #4, Updateable area", o_copro_read_data); end + 4'd 5: begin `TB_DEBUG_MESSAGE $display ("Read 0x%08h from Co-Pro 15 #4, Disruptive area", o_copro_read_data); end + 4'd 6: begin `TB_DEBUG_MESSAGE $display ("Read 0x%08h from Co-Pro 15 #6, Fault Status Register", o_copro_read_data); end + 4'd 7: begin `TB_DEBUG_MESSAGE $display ("Read 0x%08h from Co-Pro 15 #7, Fault Address Register", o_copro_read_data); end + endcase + end +//synopsys translate_on +`endif + +endmodule + diff --git a/amber/a23_core.v b/amber/a23_core.v new file mode 100644 index 0000000..415dac5 --- /dev/null +++ b/amber/a23_core.v @@ -0,0 +1,369 @@ +////////////////////////////////////////////////////////////////// +// // +// Amber 2 Core top-Level module // +// // +// This file is part of the Amber project // +// http://www.opencores.org/project,amber // +// // +// Description // +// Instantiates the core consisting of fetch, instruction // +// decode, execute, and co-processor. // +// // +// Author(s): // +// - Conor Santifort, csantifort.amber@gmail.com // +// // +////////////////////////////////////////////////////////////////// +// // +// Copyright (C) 2010 Authors and OPENCORES.ORG // +// // +// This source file may be used and distributed without // +// restriction provided that this copyright statement is not // +// removed from the file and that any derivative work contains // +// the original copyright notice and the associated disclaimer. // +// // +// This source file is free software; you can redistribute it // +// and/or modify it under the terms of the GNU Lesser General // +// Public License as published by the Free Software Foundation; // +// either version 2.1 of the License, or (at your option) any // +// later version. // +// // +// This source 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 Lesser General Public License for more // +// details. // +// // +// You should have received a copy of the GNU Lesser General // +// Public License along with this source; if not, download it // +// from http://www.opencores.org/lgpl.shtml // +// // +////////////////////////////////////////////////////////////////// + + +module a23_core +( + input i_clk, + + input i_irq, // Interrupt request, active high + input i_firq, // Fast Interrupt request, active high + + input i_system_rdy, // Amber is stalled when this is low + + // Wishbone Master I/F + output [31:0] o_wb_adr, + output [3:0] o_wb_sel, + output o_wb_we, + input [31:0] i_wb_dat, + output [31:0] o_wb_dat, + output o_wb_cyc, + output o_wb_stb, + input i_wb_ack, + input i_wb_err, + output o_wb_tga +); + +wire [31:0] execute_address; +wire execute_address_valid; +wire [31:0] execute_address_nxt; // un-registered version of execute_address to the cache rams +wire [31:0] write_data; +wire write_enable; +wire [31:0] read_data; +wire priviledged; +wire exclusive_exec; +wire data_access_exec; +wire translate; +wire [3:0] byte_enable; +wire data_access; // high for data petch, low for instruction fetch +wire exclusive; // swap access +wire cache_enable; // Enabel the cache +wire cache_flush; // Flush the cache +wire [31:0] cacheable_area; + +wire fetch_abort ; // asserted when the fetch could not be completed. +wire fetch_stall; // when this is asserted all registers in all 3 pipeline + // stages are held + // at their current values +wire [1:0] status_bits_mode; +wire status_bits_irq_mask; +wire status_bits_firq_mask; +wire status_bits_flags_wen; +wire status_bits_mode_wen; +wire status_bits_irq_mask_wen; +wire status_bits_firq_mask_wen; +wire [31:0] execute_status_bits; + +wire [31:0] imm32; +wire [4:0] imm_shift_amount; +wire shift_imm_zero; +wire [3:0] condition; +wire [31:0] read_data_s2; +wire [4:0] read_data_alignment; + +wire [3:0] rm_sel; +wire [3:0] rds_sel; +wire [3:0] rn_sel; +wire [3:0] rm_sel_nxt; +wire [3:0] rds_sel_nxt; +wire [3:0] rn_sel_nxt; +wire [1:0] barrel_shift_amount_sel; +wire [1:0] barrel_shift_data_sel; +wire [1:0] barrel_shift_function; +wire use_carry_in; +wire [8:0] alu_function; +wire [1:0] multiply_function; +wire [2:0] interrupt_vector_sel; +wire [3:0] address_sel; +wire [1:0] pc_sel; +wire writeback_sel; +wire [1:0] byte_enable_sel; +wire [2:0] status_bits_sel; +wire [2:0] reg_write_sel; +wire user_mode_regs_load; +wire user_mode_regs_store_nxt; +wire firq_not_user_mode; + +wire write_data_wen; +wire copro_write_data_wen; +wire base_address_wen; +wire pc_wen; +wire [14:0] reg_bank_wen; +wire [3:0] reg_bank_wsel; + +wire [2:0] copro_opcode1; +wire [2:0] copro_opcode2; +wire [3:0] copro_crn; +wire [3:0] copro_crm; +wire [3:0] copro_num; +wire [1:0] copro_operation; +wire [31:0] copro_read_data; +wire [31:0] copro_write_data; +wire multiply_done; + +wire decode_fault; +wire iabt_trigger; +wire dabt_trigger; + +wire [7:0] decode_fault_status; +wire [7:0] iabt_fault_status; +wire [7:0] dabt_fault_status; + +wire [31:0] decode_fault_address; +wire [31:0] iabt_fault_address; +wire [31:0] dabt_fault_address; + +wire adex; + + +// data abort has priority +assign decode_fault_status = dabt_trigger ? dabt_fault_status : iabt_fault_status; +assign decode_fault_address = dabt_trigger ? dabt_fault_address : iabt_fault_address; +assign decode_fault = dabt_trigger | iabt_trigger; + + +a23_fetch u_fetch ( + .i_clk ( i_clk ), + + .i_address ( execute_address[31:0] ), + .i_address_valid ( execute_address_valid ), + .i_address_nxt ( execute_address_nxt ), + .i_write_data ( write_data ), + .i_write_enable ( write_enable ), + .o_read_data ( read_data ), + .i_priviledged ( priviledged ), + .i_translate ( translate ), + .i_byte_enable ( byte_enable ), + .i_data_access ( data_access ), + .i_exclusive ( exclusive ), + .i_cache_enable ( cache_enable ), + .i_cache_flush ( cache_flush ), + .i_cacheable_area ( cacheable_area ), + + .i_system_rdy ( i_system_rdy ), + .o_fetch_stall ( fetch_stall ), + .o_fetch_abort ( fetch_abort ), + + .o_wb_adr ( o_wb_adr ), + .o_wb_sel ( o_wb_sel ), + .o_wb_we ( o_wb_we ), + .i_wb_dat ( i_wb_dat ), + .o_wb_dat ( o_wb_dat ), + .o_wb_cyc ( o_wb_cyc ), + .o_wb_stb ( o_wb_stb ), + .i_wb_ack ( i_wb_ack ), + .i_wb_err ( i_wb_err ), + .o_wb_tga ( o_wb_tga ) +); + + +a23_decode u_decode ( + .i_clk ( i_clk ), + + // Instruction fetch or data read signals + .i_read_data ( read_data ), + .i_execute_address ( execute_address ), + .i_adex ( adex ), + .i_iabt ( 1'd0 ), + .i_dabt ( fetch_abort ), + .i_abt_status ( 8'd0 ), + + .o_read_data ( read_data_s2 ), + .o_read_data_alignment ( read_data_alignment ), + + .i_irq ( i_irq ), + .i_firq ( i_firq ), + .i_fetch_stall ( fetch_stall ), + .i_fetch_abort ( fetch_abort ), + .i_execute_status_bits ( execute_status_bits ), + .i_multiply_done ( multiply_done ), + + .o_status_bits_mode ( status_bits_mode ), + .o_status_bits_irq_mask ( status_bits_irq_mask ), + .o_status_bits_firq_mask ( status_bits_firq_mask ), + .o_imm32 ( imm32 ), + .o_imm_shift_amount ( imm_shift_amount ), + .o_shift_imm_zero ( shift_imm_zero ), + .o_condition ( condition ), + .o_exclusive_exec ( exclusive_exec ), + .o_data_access_exec ( data_access_exec ), + .o_rm_sel ( rm_sel ), + .o_rds_sel ( rds_sel ), + .o_rn_sel ( rn_sel ), + .o_rm_sel_nxt ( rm_sel_nxt ), + .o_rds_sel_nxt ( rds_sel_nxt ), + .o_rn_sel_nxt ( rn_sel_nxt ), + .o_barrel_shift_amount_sel ( barrel_shift_amount_sel ), + .o_barrel_shift_data_sel ( barrel_shift_data_sel ), + .o_barrel_shift_function ( barrel_shift_function ), + .o_use_carry_in ( use_carry_in ), + .o_alu_function ( alu_function ), + .o_multiply_function ( multiply_function ), + .o_interrupt_vector_sel ( interrupt_vector_sel ), + .o_address_sel ( address_sel ), + .o_pc_sel ( pc_sel ), + .o_writeback_sel ( writeback_sel ), + .o_byte_enable_sel ( byte_enable_sel ), + .o_status_bits_sel ( status_bits_sel ), + .o_reg_write_sel ( reg_write_sel ), + .o_user_mode_regs_load ( user_mode_regs_load ), + .o_user_mode_regs_store_nxt ( user_mode_regs_store_nxt ), + .o_firq_not_user_mode ( firq_not_user_mode ), + .o_write_data_wen ( write_data_wen ), + .o_base_address_wen ( base_address_wen ), + .o_pc_wen ( pc_wen ), + .o_reg_bank_wen ( reg_bank_wen ), + .o_reg_bank_wsel ( reg_bank_wsel ), + .o_status_bits_flags_wen ( status_bits_flags_wen ), + .o_status_bits_mode_wen ( status_bits_mode_wen ), + .o_status_bits_irq_mask_wen ( status_bits_irq_mask_wen ), + .o_status_bits_firq_mask_wen ( status_bits_firq_mask_wen ), + + .o_copro_opcode1 ( copro_opcode1 ), + .o_copro_opcode2 ( copro_opcode2 ), + .o_copro_crn ( copro_crn ), + .o_copro_crm ( copro_crm ), + .o_copro_num ( copro_num ), + .o_copro_operation ( copro_operation ), + .o_copro_write_data_wen ( copro_write_data_wen ), + + .o_iabt_trigger ( iabt_trigger ), + .o_iabt_address ( iabt_fault_address ), + .o_iabt_status ( iabt_fault_status ), + .o_dabt_trigger ( dabt_trigger ), + .o_dabt_address ( dabt_fault_address ), + .o_dabt_status ( dabt_fault_status ) +); + + +a23_execute u_execute ( + .i_clk ( i_clk ), + + .i_read_data ( read_data_s2 ), + .i_read_data_alignment ( read_data_alignment ), + .i_copro_read_data ( copro_read_data ), + + .o_write_data ( write_data ), + .o_copro_write_data ( copro_write_data ), + .o_address ( execute_address ), + .o_address_valid ( execute_address_valid ), + .o_address_nxt ( execute_address_nxt ), + .o_adex ( adex ), + + .o_translate ( translate ), + .o_byte_enable ( byte_enable ), + .o_data_access ( data_access ), + .o_write_enable ( write_enable ), + .o_exclusive ( exclusive ), + .o_priviledged ( priviledged ), + .o_status_bits ( execute_status_bits ), + .o_multiply_done ( multiply_done ), + + .i_fetch_stall ( fetch_stall ), + .i_fetch_abort ( fetch_abort ), + .i_status_bits_mode ( status_bits_mode ), + .i_status_bits_irq_mask ( status_bits_irq_mask ), + .i_status_bits_firq_mask ( status_bits_firq_mask ), + .i_imm32 ( imm32 ), + .i_imm_shift_amount ( imm_shift_amount ), + .i_shift_imm_zero ( shift_imm_zero ), + .i_condition ( condition ), + .i_exclusive_exec ( exclusive_exec ), + .i_data_access_exec ( data_access_exec ), + .i_rm_sel ( rm_sel ), + .i_rds_sel ( rds_sel ), + .i_rn_sel ( rn_sel ), + .i_rm_sel_nxt ( rm_sel_nxt ), + .i_rds_sel_nxt ( rds_sel_nxt ), + .i_rn_sel_nxt ( rn_sel_nxt ), + .i_barrel_shift_amount_sel ( barrel_shift_amount_sel ), + .i_barrel_shift_data_sel ( barrel_shift_data_sel ), + .i_barrel_shift_function ( barrel_shift_function ), + .i_use_carry_in ( use_carry_in ), + .i_alu_function ( alu_function ), + .i_multiply_function ( multiply_function ), + .i_interrupt_vector_sel ( interrupt_vector_sel ), + .i_address_sel ( address_sel ), + .i_pc_sel ( pc_sel ), + .i_writeback_sel ( writeback_sel ), + .i_byte_enable_sel ( byte_enable_sel ), + .i_status_bits_sel ( status_bits_sel ), + .i_reg_write_sel ( reg_write_sel ), + .i_user_mode_regs_load ( user_mode_regs_load ), + .i_user_mode_regs_store_nxt ( user_mode_regs_store_nxt ), + .i_firq_not_user_mode ( firq_not_user_mode ), + .i_write_data_wen ( write_data_wen ), + .i_base_address_wen ( base_address_wen ), + .i_pc_wen ( pc_wen ), + .i_reg_bank_wen ( reg_bank_wen ), + .i_reg_bank_wsel ( reg_bank_wsel ), + .i_status_bits_flags_wen ( status_bits_flags_wen ), + .i_status_bits_mode_wen ( status_bits_mode_wen ), + .i_status_bits_irq_mask_wen ( status_bits_irq_mask_wen ), + .i_status_bits_firq_mask_wen ( status_bits_firq_mask_wen ), + .i_copro_write_data_wen ( copro_write_data_wen ) +); + + +a23_coprocessor u_coprocessor ( + .i_clk ( i_clk ), + + .i_fetch_stall ( fetch_stall ), + .i_copro_opcode1 ( copro_opcode1 ), + .i_copro_opcode2 ( copro_opcode2 ), + .i_copro_crn ( copro_crn ), + .i_copro_crm ( copro_crm ), + .i_copro_num ( copro_num ), + .i_copro_operation ( copro_operation ), + .i_copro_write_data ( copro_write_data ), + + .i_fault ( decode_fault ), + .i_fault_status ( decode_fault_status ), + .i_fault_address ( decode_fault_address ), + + .o_copro_read_data ( copro_read_data ), + .o_cache_enable ( cache_enable ), + .o_cache_flush ( cache_flush ), + .o_cacheable_area ( cacheable_area ) +); + +endmodule + diff --git a/amber/a23_decode.v b/amber/a23_decode.v new file mode 100644 index 0000000..fac8418 --- /dev/null +++ b/amber/a23_decode.v @@ -0,0 +1,1781 @@ +////////////////////////////////////////////////////////////////// +// // +// Decode stage of Amber 2 Core // +// // +// This file is part of the Amber project // +// http://www.opencores.org/project,amber // +// // +// Description // +// This module is the most complex part of the Amber core // +// It decodes and sequences all instructions and handles all // +// interrupts // +// // +// Author(s): // +// - Conor Santifort, csantifort.amber@gmail.com // +// // +////////////////////////////////////////////////////////////////// +// // +// Copyright (C) 2010 Authors and OPENCORES.ORG // +// // +// This source file may be used and distributed without // +// restriction provided that this copyright statement is not // +// removed from the file and that any derivative work contains // +// the original copyright notice and the associated disclaimer. // +// // +// This source file is free software; you can redistribute it // +// and/or modify it under the terms of the GNU Lesser General // +// Public License as published by the Free Software Foundation; // +// either version 2.1 of the License, or (at your option) any // +// later version. // +// // +// This source 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 Lesser General Public License for more // +// details. // +// // +// You should have received a copy of the GNU Lesser General // +// Public License along with this source; if not, download it // +// from http://www.opencores.org/lgpl.shtml // +// // +////////////////////////////////////////////////////////////////// + +module a23_decode +( +input i_clk, +input [31:0] i_read_data, +input i_fetch_stall, // stall all stages of the cpu at the same time +input i_fetch_abort, // abort the data transfer (instruction or data). +input i_irq, // interrupt request +input i_firq, // Fast interrupt request +input i_dabt, // data abort interrupt request +input i_iabt, // instruction pre-fetch abort flag +input i_adex, // Address Exception +input [31:0] i_execute_address, // Registered address output by execute stage + // 2 LSBs of read address used for calculating + // shift in LDRB ops +input [7:0] i_abt_status, // Abort status +input [31:0] i_execute_status_bits, // current status bits values in execute stage +input i_multiply_done, // multiply unit is nearly done + + +// -------------------------------------------------- +// Control signals to execute stage +// -------------------------------------------------- +output reg [31:0] o_read_data, +output reg [4:0] o_read_data_alignment, // 2 LSBs of read address used for calculating shift in LDRB ops + +output reg [31:0] o_imm32, +output reg [4:0] o_imm_shift_amount, +output reg o_shift_imm_zero, +output reg [3:0] o_condition, // 4'he = al +output reg o_exclusive_exec, // exclusive access request ( swap instruction ) +output reg o_data_access_exec, // high means the memory access is a read + // read or write, low for instruction +output reg [1:0] o_status_bits_mode, // SVC +output reg o_status_bits_irq_mask, +output reg o_status_bits_firq_mask, + +output reg [3:0] o_rm_sel, +output reg [3:0] o_rds_sel, +output reg [3:0] o_rn_sel, +output [3:0] o_rm_sel_nxt, +output [3:0] o_rds_sel_nxt, +output [3:0] o_rn_sel_nxt, +output reg [1:0] o_barrel_shift_amount_sel, +output reg [1:0] o_barrel_shift_data_sel, +output reg [1:0] o_barrel_shift_function, +output reg [8:0] o_alu_function, +output reg o_use_carry_in, +output reg [1:0] o_multiply_function, +output reg [2:0] o_interrupt_vector_sel, +output reg [3:0] o_address_sel, +output reg [1:0] o_pc_sel, +output reg [1:0] o_byte_enable_sel, // byte, halfword or word write +output reg [2:0] o_status_bits_sel, +output reg [2:0] o_reg_write_sel, +output reg o_user_mode_regs_load, +output reg o_user_mode_regs_store_nxt, +output reg o_firq_not_user_mode, + +output reg o_write_data_wen, +output reg o_base_address_wen, // save LDM base address register + // in case of data abort +output reg o_pc_wen, +output reg o_writeback_sel, // force supervisor mode off for the memory cycle. +output reg [14:0] o_reg_bank_wen, +output reg [3:0] o_reg_bank_wsel, +output reg o_status_bits_flags_wen, +output reg o_status_bits_mode_wen, +output reg o_status_bits_irq_mask_wen, +output reg o_status_bits_firq_mask_wen, + +// -------------------------------------------------- +// Co-Processor interface +// -------------------------------------------------- +output reg [2:0] o_copro_opcode1, +output reg [2:0] o_copro_opcode2, +output reg [3:0] o_copro_crn, +output reg [3:0] o_copro_crm, +output reg [3:0] o_copro_num, +output reg [1:0] o_copro_operation, // 0 = no operation, + // 1 = Move to Amber Core Register from Coprocessor + // 2 = Move to Coprocessor from Amber Core Register +output reg o_copro_write_data_wen, +output o_iabt_trigger, +output [31:0] o_iabt_address, +output [7:0] o_iabt_status, +output o_dabt_trigger, +output [31:0] o_dabt_address, +output [7:0] o_dabt_status + + +); + +`include "a23_localparams.v" +`include "a23_functions.v" + +localparam [4:0] RST_WAIT1 = 5'd0, + RST_WAIT2 = 5'd1, + INT_WAIT1 = 5'd2, + INT_WAIT2 = 5'd3, + EXECUTE = 5'd4, + PRE_FETCH_EXEC = 5'd5, // Execute the Pre-Fetched Instruction + MEM_WAIT1 = 5'd6, // conditionally decode current instruction, in case + // previous instruction does not execute in S2 + MEM_WAIT2 = 5'd7, + PC_STALL1 = 5'd8, // Program Counter altered + // conditionally decude current instruction, in case + // previous instruction does not execute in S2 + PC_STALL2 = 5'd9, + MTRANS_EXEC1 = 5'd10, + MTRANS_EXEC2 = 5'd11, + MTRANS_EXEC3 = 5'd12, + MTRANS_EXEC3B = 5'd13, + MTRANS_EXEC4 = 5'd14, + MTRANS5_ABORT = 5'd15, + MULT_PROC1 = 5'd16, // first cycle, save pre fetch instruction + MULT_PROC2 = 5'd17, // do multiplication + MULT_STORE = 5'd19, // save RdLo + MULT_ACCUMU = 5'd20, // Accumulate add lower 32 bits + SWAP_WRITE = 5'd22, + SWAP_WAIT1 = 5'd23, + SWAP_WAIT2 = 5'd24, + COPRO_WAIT = 5'd25; + + +// ======================================================== +// Internal signals +// ======================================================== +wire [31:0] instruction; +wire instruction_iabt; // abort flag, follows the instruction +wire instruction_adex; // address exception flag, follows the instruction +wire [31:0] instruction_address; // instruction virtual address, follows + // the instruction +wire [7:0] instruction_iabt_status; // abort status, follows the instruction +wire [1:0] instruction_sel; +reg [3:0] itype; +wire [3:0] opcode; +wire [7:0] imm8; +wire [31:0] offset12; +wire [31:0] offset24; +wire [4:0] shift_imm; + +wire opcode_compare; +wire mem_op; +wire load_op; +wire store_op; +wire write_pc; +wire immediate_shifter_operand; +wire rds_use_rs; +wire branch; +wire mem_op_pre_indexed; +wire mem_op_post_indexed; + +// Flop inputs +wire [31:0] imm32_nxt; +wire [4:0] imm_shift_amount_nxt; +wire shift_imm_zero_nxt; +wire [3:0] condition_nxt; +reg exclusive_exec_nxt; +reg data_access_exec_nxt; + +reg [1:0] barrel_shift_function_nxt; +wire [8:0] alu_function_nxt; +reg use_carry_in_nxt; +reg [1:0] multiply_function_nxt; +reg [1:0] status_bits_mode_nxt; +reg status_bits_irq_mask_nxt; +reg status_bits_firq_mask_nxt; + +reg [1:0] barrel_shift_amount_sel_nxt; +reg [1:0] barrel_shift_data_sel_nxt; +reg [3:0] address_sel_nxt; +reg [1:0] pc_sel_nxt; +reg writeback_sel_nxt; +reg [1:0] byte_enable_sel_nxt; +reg [2:0] status_bits_sel_nxt; +reg [2:0] reg_write_sel_nxt; +reg user_mode_regs_load_nxt; +wire firq_not_user_mode_nxt; + +// ALU Function signals +reg alu_swap_sel_nxt; +reg alu_not_sel_nxt; +reg [1:0] alu_cin_sel_nxt; +reg alu_cout_sel_nxt; +reg [3:0] alu_out_sel_nxt; + +reg write_data_wen_nxt; +reg copro_write_data_wen_nxt; +reg base_address_wen_nxt; +reg pc_wen_nxt; +reg [3:0] reg_bank_wsel_nxt; +reg status_bits_flags_wen_nxt; +reg status_bits_mode_wen_nxt; +reg status_bits_irq_mask_wen_nxt; +reg status_bits_firq_mask_wen_nxt; + +reg saved_current_instruction_wen; // saved load instruction +reg pre_fetch_instruction_wen; // pre-fetch instruction + +reg [4:0] control_state = RST_WAIT1; +reg [4:0] control_state_nxt; + + +wire dabt; +reg dabt_reg = 'd0; +reg iabt_reg = 'd0; +reg adex_reg = 'd0; +reg [31:0] abt_address_reg = 'd0; +reg [7:0] abt_status_reg = 'd0; +reg [31:0] saved_current_instruction = 'd0; +reg saved_current_instruction_iabt = 'd0; // access abort flag +reg saved_current_instruction_adex = 'd0; // address exception +reg [31:0] saved_current_instruction_address = 'd0; // virtual address of abort instruction +reg [7:0] saved_current_instruction_iabt_status = 'd0; // status of abort instruction +reg [31:0] pre_fetch_instruction = 'd0; +reg pre_fetch_instruction_iabt = 'd0; // access abort flag +reg pre_fetch_instruction_adex = 'd0; // address exception +reg [31:0] pre_fetch_instruction_address = 'd0; // virtual address of abort instruction +reg [7:0] pre_fetch_instruction_iabt_status = 'd0; // status of abort instruction + +wire instruction_valid; +wire instruction_execute; + +reg [3:0] mtrans_reg; // the current register being accessed as part of STM/LDM +reg [3:0] mtrans_reg_d1 = 'd0; // delayed by 1 period +reg [3:0] mtrans_reg_d2 = 'd0; // delayed by 2 periods +reg [31:0] mtrans_instruction_nxt; + +wire [31:0] mtrans_base_reg_change; +wire [4:0] mtrans_num_registers; +wire use_saved_current_instruction; +wire use_pre_fetch_instruction; +wire interrupt; +wire [1:0] interrupt_mode; +wire [2:0] next_interrupt; +reg irq = 'd0; +reg firq = 'd0; +wire firq_request; +wire irq_request; +wire swi_request; +wire und_request; +wire dabt_request; +reg [1:0] copro_operation_nxt; +reg mtrans_r15 = 'd0; +reg mtrans_r15_nxt; +reg restore_base_address = 'd0; +reg restore_base_address_nxt; + +wire regop_set_flags; + + +// ======================================================== +// Instruction Abort and Data Abort outputs +// ======================================================== + +assign o_iabt_trigger = instruction_iabt && o_status_bits_mode == SVC && control_state == INT_WAIT1; +assign o_iabt_address = instruction_address; +assign o_iabt_status = instruction_iabt_status; + +assign o_dabt_trigger = dabt_reg; +assign o_dabt_address = abt_address_reg; +assign o_dabt_status = abt_status_reg; + + +// ======================================================== +// Instruction Decode +// ======================================================== + +// for instructions that take more than one cycle +// the instruction is saved in the 'saved_mem_instruction' +// register and then that register is used for the rest of +// the execution of the instruction. +// But if the instruction does not execute because of the +// condition, then need to select the next instruction to +// decode +assign use_saved_current_instruction = instruction_execute && + ( control_state == MEM_WAIT1 || + control_state == MEM_WAIT2 || + control_state == MTRANS_EXEC1 || + control_state == MTRANS_EXEC2 || + control_state == MTRANS_EXEC3 || + control_state == MTRANS_EXEC3B || + control_state == MTRANS_EXEC4 || + control_state == MTRANS5_ABORT || + control_state == MULT_PROC1 || + control_state == MULT_PROC2 || + control_state == MULT_ACCUMU || + control_state == MULT_STORE || + control_state == INT_WAIT1 || + control_state == INT_WAIT2 || + control_state == SWAP_WRITE || + control_state == SWAP_WAIT1 || + control_state == SWAP_WAIT2 || + control_state == COPRO_WAIT ); + +assign use_pre_fetch_instruction = control_state == PRE_FETCH_EXEC; + + +assign instruction_sel = use_saved_current_instruction ? 2'd1 : // saved_current_instruction + use_pre_fetch_instruction ? 2'd2 : // pre_fetch_instruction + 2'd0 ; // o_read_data + +assign instruction = instruction_sel == 2'd0 ? o_read_data : + instruction_sel == 2'd1 ? saved_current_instruction : + pre_fetch_instruction ; + +// abort flag +assign instruction_iabt = instruction_sel == 2'd0 ? iabt_reg : + instruction_sel == 2'd1 ? saved_current_instruction_iabt : + pre_fetch_instruction_iabt ; + +assign instruction_address = instruction_sel == 2'd0 ? abt_address_reg : + instruction_sel == 2'd1 ? saved_current_instruction_address : + pre_fetch_instruction_address ; + +assign instruction_iabt_status = instruction_sel == 2'd0 ? abt_status_reg : + instruction_sel == 2'd1 ? saved_current_instruction_iabt_status : + pre_fetch_instruction_iabt_status ; + +// instruction address exception +assign instruction_adex = instruction_sel == 2'd0 ? adex_reg : + instruction_sel == 2'd1 ? saved_current_instruction_adex : + pre_fetch_instruction_adex ; + +// Instruction Decode - Order is important! +always @* + casez ({instruction[27:20], instruction[7:4]}) + 12'b00010?001001 : itype = SWAP; + 12'b000000??1001 : itype = MULT; + 12'b00?????????? : itype = REGOP; + 12'b01?????????? : itype = TRANS; + 12'b100????????? : itype = MTRANS; + 12'b101????????? : itype = BRANCH; + 12'b110????????? : itype = CODTRANS; + 12'b1110???????0 : itype = COREGOP; + 12'b1110???????1 : itype = CORTRANS; + default: itype = SWI; + endcase + + +// ======================================================== +// Fixed fields within the instruction +// ======================================================== + +assign opcode = instruction[24:21]; +assign condition_nxt = instruction[31:28]; + +assign o_rm_sel_nxt = instruction[3:0]; + +assign o_rn_sel_nxt = branch ? 4'd15 : // Use PC to calculate branch destination + instruction[19:16] ; + +assign o_rds_sel_nxt = control_state == SWAP_WRITE ? instruction[3:0] : // Rm gets written out to memory + itype == MTRANS ? mtrans_reg : + branch ? 4'd15 : // Update the PC + rds_use_rs ? instruction[11:8] : + instruction[15:12] ; + + +assign shift_imm = instruction[11:7]; +// this is used for RRX +wire shift_extend = ~instruction[25] & ~instruction[4] & ~(|instruction[11:7]) & instruction[6:5] == 2'b11; + +assign offset12 = { 20'h0, instruction[11:0]}; +assign offset24 = {{6{instruction[23]}}, instruction[23:0], 2'd0 }; // sign extend +assign imm8 = instruction[7:0]; + +assign immediate_shifter_operand = instruction[25]; +assign rds_use_rs = (itype == REGOP && !instruction[25] && instruction[4]) || + (itype == MULT && + (control_state == MULT_PROC1 || + control_state == MULT_PROC2 || + instruction_valid && !interrupt )) ; +assign branch = itype == BRANCH; +assign opcode_compare = + opcode == CMP || + opcode == CMN || + opcode == TEQ || + opcode == TST ; + + +assign mem_op = itype == TRANS; +assign load_op = mem_op && instruction[20]; +assign store_op = mem_op && !instruction[20]; +assign write_pc = pc_wen_nxt && pc_sel_nxt != 2'd0; +assign regop_set_flags = itype == REGOP && instruction[20]; + +assign mem_op_pre_indexed = instruction[24] && instruction[21]; +assign mem_op_post_indexed = !instruction[24]; + +assign imm32_nxt = // add 0 to Rm + itype == MULT ? { 32'd0 } : + + // 4 x number of registers + itype == MTRANS ? { mtrans_base_reg_change } : + itype == BRANCH ? { offset24 } : + itype == TRANS ? { offset12 } : + instruction[11:8] == 4'h0 ? { 24'h0, imm8[7:0] } : + instruction[11:8] == 4'h1 ? { imm8[1:0], 24'h0, imm8[7:2] } : + instruction[11:8] == 4'h2 ? { imm8[3:0], 24'h0, imm8[7:4] } : + instruction[11:8] == 4'h3 ? { imm8[5:0], 24'h0, imm8[7:6] } : + instruction[11:8] == 4'h4 ? { imm8[7:0], 24'h0 } : + instruction[11:8] == 4'h5 ? { 2'h0, imm8[7:0], 22'h0 } : + instruction[11:8] == 4'h6 ? { 4'h0, imm8[7:0], 20'h0 } : + instruction[11:8] == 4'h7 ? { 6'h0, imm8[7:0], 18'h0 } : + instruction[11:8] == 4'h8 ? { 8'h0, imm8[7:0], 16'h0 } : + instruction[11:8] == 4'h9 ? { 10'h0, imm8[7:0], 14'h0 } : + instruction[11:8] == 4'ha ? { 12'h0, imm8[7:0], 12'h0 } : + instruction[11:8] == 4'hb ? { 14'h0, imm8[7:0], 10'h0 } : + instruction[11:8] == 4'hc ? { 16'h0, imm8[7:0], 8'h0 } : + instruction[11:8] == 4'hd ? { 18'h0, imm8[7:0], 6'h0 } : + instruction[11:8] == 4'he ? { 20'h0, imm8[7:0], 4'h0 } : + { 22'h0, imm8[7:0], 2'h0 } ; + + +assign imm_shift_amount_nxt = shift_imm ; + + // This signal is encoded in the decode stage because + // it is on the critical path in the execute stage +assign shift_imm_zero_nxt = imm_shift_amount_nxt == 5'd0 && // immediate amount = 0 + barrel_shift_amount_sel_nxt == 2'd2; // shift immediate amount + +assign alu_function_nxt = { alu_swap_sel_nxt, + alu_not_sel_nxt, + alu_cin_sel_nxt, + alu_cout_sel_nxt, + alu_out_sel_nxt }; + + +// ======================================================== +// MTRANS Operations +// ======================================================== + + // Bit 15 = r15 + // Bit 0 = R0 + // In LDM and STM instructions R0 is loaded or stored first +always @* + casez (instruction[15:0]) + 16'b???????????????1 : mtrans_reg = 4'h0 ; + 16'b??????????????10 : mtrans_reg = 4'h1 ; + 16'b?????????????100 : mtrans_reg = 4'h2 ; + 16'b????????????1000 : mtrans_reg = 4'h3 ; + 16'b???????????10000 : mtrans_reg = 4'h4 ; + 16'b??????????100000 : mtrans_reg = 4'h5 ; + 16'b?????????1000000 : mtrans_reg = 4'h6 ; + 16'b????????10000000 : mtrans_reg = 4'h7 ; + 16'b???????100000000 : mtrans_reg = 4'h8 ; + 16'b??????1000000000 : mtrans_reg = 4'h9 ; + 16'b?????10000000000 : mtrans_reg = 4'ha ; + 16'b????100000000000 : mtrans_reg = 4'hb ; + 16'b???1000000000000 : mtrans_reg = 4'hc ; + 16'b??10000000000000 : mtrans_reg = 4'hd ; + 16'b?100000000000000 : mtrans_reg = 4'he ; + default : mtrans_reg = 4'hf ; + endcase + +always @* + casez (instruction[15:0]) + 16'b???????????????1 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 1], 1'd0}; + 16'b??????????????10 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 2], 2'd0}; + 16'b?????????????100 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 3], 3'd0}; + 16'b????????????1000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 4], 4'd0}; + 16'b???????????10000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 5], 5'd0}; + 16'b??????????100000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 6], 6'd0}; + 16'b?????????1000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 7], 7'd0}; + 16'b????????10000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 8], 8'd0}; + 16'b???????100000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15: 9], 9'd0}; + 16'b??????1000000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15:10], 10'd0}; + 16'b?????10000000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15:11], 11'd0}; + 16'b????100000000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15:12], 12'd0}; + 16'b???1000000000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15:13], 13'd0}; + 16'b??10000000000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15:14], 14'd0}; + 16'b?100000000000000 : mtrans_instruction_nxt = {instruction[31:16], instruction[15 ], 15'd0}; + default : mtrans_instruction_nxt = {instruction[31:16], 16'd0}; + endcase + + +// number of registers to be stored +assign mtrans_num_registers = {4'd0, instruction[15]} + + {4'd0, instruction[14]} + + {4'd0, instruction[13]} + + {4'd0, instruction[12]} + + {4'd0, instruction[11]} + + {4'd0, instruction[10]} + + {4'd0, instruction[ 9]} + + {4'd0, instruction[ 8]} + + {4'd0, instruction[ 7]} + + {4'd0, instruction[ 6]} + + {4'd0, instruction[ 5]} + + {4'd0, instruction[ 4]} + + {4'd0, instruction[ 3]} + + {4'd0, instruction[ 2]} + + {4'd0, instruction[ 1]} + + {4'd0, instruction[ 0]} ; + +// 4 x number of registers to be stored +assign mtrans_base_reg_change = {25'd0, mtrans_num_registers, 2'd0}; + +// ======================================================== +// Interrupts +// ======================================================== + +assign firq_request = firq && !i_execute_status_bits[26]; +assign irq_request = irq && !i_execute_status_bits[27]; +assign swi_request = itype == SWI; +assign dabt_request = dabt_reg || i_dabt; + +// copro15 and copro13 only supports reg trans opcodes +// all other opcodes involving co-processors cause an +// undefined instrution interrupt +assign und_request = itype == CODTRANS || + itype == COREGOP || + ( itype == CORTRANS && instruction[11:8] != 4'd15 ); + + + // in order of priority !! + // Highest + // 1 Reset + // 2 Data Abort (including data TLB miss) + // 3 FIRQ + // 4 IRQ + // 5 Prefetch Abort (including prefetch TLB miss) + // 6 Undefined instruction, SWI + // Lowest +assign next_interrupt = dabt_request ? 3'd1 : // Data Abort + firq_request ? 3'd2 : // FIRQ + irq_request ? 3'd3 : // IRQ + instruction_adex ? 3'd4 : // Address Exception + instruction_iabt ? 3'd5 : // PreFetch Abort, only triggered + // if the instruction is used + und_request ? 3'd6 : // Undefined Instruction + swi_request ? 3'd7 : // SWI + 3'd0 ; // none + + // SWI and undefined instructions do not cause an interrupt in the decode + // stage. They only trigger interrupts if they arfe executed, so the + // interrupt is triggered if the execute condition is met in the execute stage +assign interrupt = next_interrupt != 3'd0 && + next_interrupt != 3'd7 && // SWI + next_interrupt != 3'd6 ; // undefined interrupt + + +assign interrupt_mode = next_interrupt == 3'd2 ? FIRQ : + next_interrupt == 3'd3 ? IRQ : + next_interrupt == 3'd4 ? SVC : + next_interrupt == 3'd5 ? SVC : + next_interrupt == 3'd6 ? SVC : + next_interrupt == 3'd7 ? SVC : + next_interrupt == 3'd1 ? SVC : + USR ; + + + + +// ======================================================== +// Generate control signals +// ======================================================== +always @* + begin + // default mode + status_bits_mode_nxt = i_execute_status_bits[1:0]; // change to mode in execute stage get reflected + // back to this stage automatically + status_bits_irq_mask_nxt = o_status_bits_irq_mask; + status_bits_firq_mask_nxt = o_status_bits_firq_mask; + exclusive_exec_nxt = 1'd0; + data_access_exec_nxt = 1'd0; + copro_operation_nxt = 'd0; + + // Save an instruction to use later + saved_current_instruction_wen = 1'd0; + pre_fetch_instruction_wen = 1'd0; + mtrans_r15_nxt = mtrans_r15; + restore_base_address_nxt = restore_base_address; + + // default Mux Select values + barrel_shift_amount_sel_nxt = 'd0; // don't shift the input + barrel_shift_data_sel_nxt = 'd0; // immediate value + barrel_shift_function_nxt = 'd0; + use_carry_in_nxt = 'd0; + multiply_function_nxt = 'd0; + address_sel_nxt = 'd0; + pc_sel_nxt = 'd0; + writeback_sel_nxt = 'd0; + byte_enable_sel_nxt = 'd0; + status_bits_sel_nxt = 'd0; + reg_write_sel_nxt = 'd0; + user_mode_regs_load_nxt = 'd0; + o_user_mode_regs_store_nxt = 'd0; + + // ALU Muxes + alu_swap_sel_nxt = 'd0; + alu_not_sel_nxt = 'd0; + alu_cin_sel_nxt = 'd0; + alu_cout_sel_nxt = 'd0; + alu_out_sel_nxt = 'd0; + + // default Flop Write Enable values + write_data_wen_nxt = 'd0; + copro_write_data_wen_nxt = 'd0; + base_address_wen_nxt = 'd0; + pc_wen_nxt = 'd1; + reg_bank_wsel_nxt = 'hF; // Don't select any + status_bits_flags_wen_nxt = 'd0; + status_bits_mode_wen_nxt = 'd0; + status_bits_irq_mask_wen_nxt = 'd0; + status_bits_firq_mask_wen_nxt = 'd0; + + if ( instruction_valid && !interrupt ) + begin + if ( itype == REGOP ) + begin + if ( !opcode_compare ) + begin + // Check is the load destination is the PC + if (instruction[15:12] == 4'd15) + begin + pc_sel_nxt = 2'd1; // alu_out + address_sel_nxt = 4'd1; // alu_out + end + else + reg_bank_wsel_nxt = instruction[15:12]; + end + + if ( !immediate_shifter_operand ) + barrel_shift_function_nxt = instruction[6:5]; + + if ( !immediate_shifter_operand ) + barrel_shift_data_sel_nxt = 2'd2; // Shift value from Rm register + + if ( !immediate_shifter_operand && instruction[4] ) + barrel_shift_amount_sel_nxt = 2'd1; // Shift amount from Rs registter + + if ( !immediate_shifter_operand && !instruction[4] ) + barrel_shift_amount_sel_nxt = 2'd2; // Shift immediate amount + + // regops that do not change the overflow flag + if ( opcode == AND || opcode == EOR || opcode == TST || opcode == TEQ || + opcode == ORR || opcode == MOV || opcode == BIC || opcode == MVN ) + status_bits_sel_nxt = 3'd5; + + if ( opcode == ADD || opcode == CMN ) // CMN is just like an ADD + begin + alu_out_sel_nxt = 4'd1; // Add + use_carry_in_nxt = shift_extend; + end + + if ( opcode == ADC ) // Add with Carry + begin + alu_out_sel_nxt = 4'd1; // Add + alu_cin_sel_nxt = 2'd2; // carry in from status_bits + use_carry_in_nxt = 1'd1; + end + + if ( opcode == SUB || opcode == CMP ) // Subtract + begin + alu_out_sel_nxt = 4'd1; // Add + alu_cin_sel_nxt = 2'd1; // cin = 1 + alu_not_sel_nxt = 1'd1; // invert B + use_carry_in_nxt = shift_extend; + + end + + // SBC (Subtract with Carry) subtracts the value of its + // second operand and the value of NOT(Carry flag) from + // the value of its first operand. + // Rd = Rn - shifter_operand - NOT(C Flag) + if ( opcode == SBC ) // Subtract with Carry + begin + alu_out_sel_nxt = 4'd1; // Add + alu_cin_sel_nxt = 2'd2; // carry in from status_bits + alu_not_sel_nxt = 1'd1; // invert B + use_carry_in_nxt = 1'd1; + end + + if ( opcode == RSB ) // Reverse Subtract + begin + alu_out_sel_nxt = 4'd1; // Add + alu_cin_sel_nxt = 2'd1; // cin = 1 + alu_not_sel_nxt = 1'd1; // invert B + alu_swap_sel_nxt = 1'd1; // swap A and B + use_carry_in_nxt = 1'd1; + end + + if ( opcode == RSC ) // Reverse Subtract with carry + begin + alu_out_sel_nxt = 4'd1; // Add + alu_cin_sel_nxt = 2'd2; // carry in from status_bits + alu_not_sel_nxt = 1'd1; // invert B + alu_swap_sel_nxt = 1'd1; // swap A and B + use_carry_in_nxt = 1'd1; + end + + if ( opcode == AND || opcode == TST ) // Logical AND, Test (using AND operator) + begin + alu_out_sel_nxt = 4'd8; // AND + alu_cout_sel_nxt = 1'd1; // i_barrel_shift_carry + use_carry_in_nxt = 1'd1; + end + + if ( opcode == EOR || opcode == TEQ ) // Logical Exclusive OR, Test Equivalence (using EOR operator) + begin + alu_out_sel_nxt = 4'd6; // XOR + alu_cout_sel_nxt = 1'd1; // i_barrel_shift_carry + use_carry_in_nxt = 1'd1; + end + + if ( opcode == ORR ) + begin + alu_out_sel_nxt = 4'd7; // OR + alu_cout_sel_nxt = 1'd1; // i_barrel_shift_carry + use_carry_in_nxt = 1'd1; + end + + if ( opcode == BIC ) // Bit Clear (using AND & NOT operators) + begin + alu_out_sel_nxt = 4'd8; // AND + alu_not_sel_nxt = 1'd1; // invert B + alu_cout_sel_nxt = 1'd1; // i_barrel_shift_carry + use_carry_in_nxt = 1'd1; + end + + if ( opcode == MOV ) // Move + begin + alu_cout_sel_nxt = 1'd1; // i_barrel_shift_carry + use_carry_in_nxt = 1'd1; + end + + if ( opcode == MVN ) // Move NOT + begin + alu_not_sel_nxt = 1'd1; // invert B + alu_cout_sel_nxt = 1'd1; // i_barrel_shift_carry + use_carry_in_nxt = 1'd1; + end + end + + // Load & Store instructions + if ( mem_op ) + begin + saved_current_instruction_wen = 1'd1; // Save the memory access instruction to refer back to later + pc_wen_nxt = 1'd0; // hold current PC value + data_access_exec_nxt = 1'd1; // indicate that its a data read or write, + // rather than an instruction fetch + alu_out_sel_nxt = 4'd1; // Add + + if ( !instruction[23] ) // U: Subtract offset + begin + alu_cin_sel_nxt = 2'd1; // cin = 1 + alu_not_sel_nxt = 1'd1; // invert B + end + + if ( store_op ) + begin + write_data_wen_nxt = 1'd1; + if ( itype == TRANS && instruction[22] ) + byte_enable_sel_nxt = 2'd1; // Save byte + end + + // need to update the register holding the address ? + // This is Rn bits [19:16] + if ( mem_op_pre_indexed || mem_op_post_indexed ) + begin + // Check is the load destination is the PC + if ( o_rn_sel_nxt == 4'd15 ) + pc_sel_nxt = 2'd1; + else + reg_bank_wsel_nxt = o_rn_sel_nxt; + end + + // post indexed transfer + // set the W bit. + if ((itype == TRANS) & mem_op_post_indexed) begin + + writeback_sel_nxt = instruction[21]; + + end + // if post-indexed, then use Rn rather than ALU output, as address + if ( mem_op_post_indexed ) + address_sel_nxt = 4'd4; // Rn + else + address_sel_nxt = 4'd1; // alu out + + if ( instruction[25] && itype == TRANS ) + barrel_shift_data_sel_nxt = 2'd2; // Shift value from Rm register + + if ( itype == TRANS && instruction[25] && shift_imm != 5'd0 ) + begin + barrel_shift_function_nxt = instruction[6:5]; + barrel_shift_amount_sel_nxt = 2'd2; // imm_shift_amount + end + end + + if ( itype == BRANCH ) + begin + pc_sel_nxt = 2'd1; // alu_out + address_sel_nxt = 4'd1; // alu_out + alu_out_sel_nxt = 4'd1; // Add + + if ( instruction[24] ) // Link + begin + reg_bank_wsel_nxt = 4'd14; // Save PC to LR + reg_write_sel_nxt = 3'd1; // pc - 32'd4 + end + end + + if ( itype == MTRANS ) + begin + saved_current_instruction_wen = 1'd1; // Save the memory access instruction to refer back to later + pc_wen_nxt = 1'd0; // hold current PC value + data_access_exec_nxt = 1'd1; // indicate that its a data read or write, + // rather than an instruction fetch + alu_out_sel_nxt = 4'd1; // Add + mtrans_r15_nxt = instruction[15]; // load or save r15 ? + base_address_wen_nxt = 1'd1; // Save the value of the register used for the base address, + // in case of a data abort, and need to restore the value + + // The spec says - + // If the instruction would have overwritten the base with data + // (that is, it has the base in the transfer list), the overwriting is prevented. + // This is true even when the abort occurs after the base word gets loaded + restore_base_address_nxt = instruction[20] && + (instruction[15:0] & (1'd1 << instruction[19:16])); + + // Increment or Decrement + if ( instruction[23] ) // increment + begin + if ( instruction[24] ) // increment before + address_sel_nxt = 4'd7; // Rn + 4 + else + address_sel_nxt = 4'd4; // Rn + end + else // decrement + begin + alu_cin_sel_nxt = 2'd1; // cin = 1 + alu_not_sel_nxt = 1'd1; // invert B + if ( !instruction[24] ) // decrement after + address_sel_nxt = 4'd6; // alu out + 4 + else + address_sel_nxt = 4'd1; // alu out + end + + // Load or store ? + if ( !instruction[20] ) // Store + write_data_wen_nxt = 1'd1; + + // LDM: load into user mode registers, when in priviledged mode + // DOnt use mtrans_r15 here because its not loaded yet + if ( {instruction[22:20],instruction[15]} == 4'b1010 ) + user_mode_regs_load_nxt = 1'd1; + + // SDM: store the user mode registers, when in priviledged mode + if ( {instruction[22:20]} == 3'b100 ) + o_user_mode_regs_store_nxt = 1'd1; + + // update the base register ? + if ( instruction[21] ) // the W bit + reg_bank_wsel_nxt = o_rn_sel_nxt; + end + + + if ( itype == MULT ) + begin + multiply_function_nxt[0] = 1'd1; // set enable + // some bits can be changed just below + saved_current_instruction_wen = 1'd1; // Save the Multiply instruction to + // refer back to later + pc_wen_nxt = 1'd0; // hold current PC value + + if ( instruction[21] ) + multiply_function_nxt[1] = 1'd1; // accumulate + end + + + // swp - do read part first + if ( itype == SWAP ) + begin + saved_current_instruction_wen = 1'd1; // Save the memory access instruction to refer back to later + pc_wen_nxt = 1'd0; // hold current PC value + data_access_exec_nxt = 1'd1; // indicate that its a data read or write, + // rather than an instruction fetch + barrel_shift_data_sel_nxt = 2'd2; // Shift value from Rm register + address_sel_nxt = 4'd4; // Rn + exclusive_exec_nxt = 1'd1; // signal an exclusive access + end + + + // mcr & mrc - takes two cycles + if ( itype == CORTRANS && !und_request ) + begin + saved_current_instruction_wen = 1'd1; // Save the memory access instruction to refer back to later + pc_wen_nxt = 1'd0; // hold current PC value + address_sel_nxt = 4'd3; // pc (not pc + 4) + + if ( instruction[20] ) // MRC + copro_operation_nxt = 2'd1; // Register transfer from Co-Processor + else // MCR + begin + // Don't enable operation to Co-Processor until next period + // So it gets the Rd value from the execution stage at the same time + copro_operation_nxt = 2'd0; + copro_write_data_wen_nxt = 1'd1; // Rd register value to co-processor + end + end + + + if ( itype == SWI || und_request ) + begin + // save address of next instruction to Supervisor Mode LR + reg_write_sel_nxt = 3'd1; // pc -4 + reg_bank_wsel_nxt = 4'd14; // LR + + address_sel_nxt = 4'd2; // interrupt_vector + pc_sel_nxt = 2'd2; // interrupt_vector + + status_bits_mode_nxt = interrupt_mode; // e.g. Supervisor mode + status_bits_mode_wen_nxt = 1'd1; + + // disable normal interrupts + status_bits_irq_mask_nxt = 1'd1; + status_bits_irq_mask_wen_nxt = 1'd1; + end + + + if ( regop_set_flags ) + begin + status_bits_flags_wen_nxt = 1'd1; + + // If is r15, the ALU output is copied to the Status Bits. + // Not allowed to use r15 for mul or lma instructions + if ( instruction[15:12] == 4'd15 ) + begin + status_bits_sel_nxt = 3'd1; // alu out + + // Priviledged mode? Then also update the other status bits + if ( i_execute_status_bits[1:0] != USR ) + begin + status_bits_mode_wen_nxt = 1'd1; + status_bits_irq_mask_wen_nxt = 1'd1; + status_bits_firq_mask_wen_nxt = 1'd1; + end + end + end + + end + + // Handle asynchronous interrupts. + // interrupts are processed only during execution states + // multicycle instructions must complete before the interrupt starts + // SWI, Address Exception and Undefined Instruction interrupts are only executed if the + // instruction that causes the interrupt is conditionally executed so + // its not handled here + if ( instruction_valid && interrupt && next_interrupt != 3'd6 ) + begin + // Save the interrupt causing instruction to refer back to later + // This also saves the instruction abort vma and status, in the case of an + // instruction abort interrupt + saved_current_instruction_wen = 1'd1; + + // save address of next instruction to Supervisor Mode LR + // Address Exception ? + if ( next_interrupt == 3'd4 ) + reg_write_sel_nxt = 3'd7; // pc + else + reg_write_sel_nxt = 3'd1; // pc -4 + + reg_bank_wsel_nxt = 4'd14; // LR + + address_sel_nxt = 4'd2; // interrupt_vector + pc_sel_nxt = 2'd2; // interrupt_vector + + status_bits_mode_nxt = interrupt_mode; // e.g. Supervisor mode + status_bits_mode_wen_nxt = 1'd1; + + // disable normal interrupts + status_bits_irq_mask_nxt = 1'd1; + status_bits_irq_mask_wen_nxt = 1'd1; + + // disable fast interrupts + if ( next_interrupt == 3'd2 ) // FIRQ + begin + status_bits_firq_mask_nxt = 1'd1; + status_bits_firq_mask_wen_nxt = 1'd1; + end + end + + + // previous instruction was either ldr or sdr + // if it is currently executing in the execute stage do the following + if ( control_state == MEM_WAIT1 ) + begin + // Save the next instruction to execute later + // Do this even if this instruction does not execute because of Condition + pre_fetch_instruction_wen = 1'd1; + + if ( instruction_execute ) // conditional execution state + begin + address_sel_nxt = 4'd3; // pc (not pc + 4) + pc_wen_nxt = 1'd0; // hold current PC value + end + end + + + // completion of load operation + if ( control_state == MEM_WAIT2 && load_op ) + begin + barrel_shift_data_sel_nxt = 2'd1; // load word from memory + barrel_shift_amount_sel_nxt = 2'd3; // shift by address[1:0] x 8 + + // shift needed + if ( i_execute_address[1:0] != 2'd0 ) + barrel_shift_function_nxt = ROR; + + // load a byte + if ( itype == TRANS && instruction[22] ) + alu_out_sel_nxt = 4'd3; // zero_extend8 + + if ( !dabt ) // dont load data there is an abort on the data read + begin + // Check if the load destination is the PC + if (instruction[15:12] == 4'd15) + begin + pc_sel_nxt = 2'd1; // alu_out + address_sel_nxt = 4'd1; // alu_out + end + else + reg_bank_wsel_nxt = instruction[15:12]; + end + end + + + // second cycle of multiple load or store + if ( control_state == MTRANS_EXEC1 ) + begin + // Save the next instruction to execute later + // Do this even if this instruction does not execute because of Condition + pre_fetch_instruction_wen = 1'd1; + + if ( instruction_execute ) // conditional execution state + begin + address_sel_nxt = 4'd5; // o_address + pc_wen_nxt = 1'd0; // hold current PC value + data_access_exec_nxt = 1'd1; // indicate that its a data read or write, + // rather than an instruction fetch + + if ( !instruction[20] ) // Store + write_data_wen_nxt = 1'd1; + + // LDM: load into user mode registers, when in priviledged mode + if ( {instruction[22:20],mtrans_r15} == 4'b1010 ) + user_mode_regs_load_nxt = 1'd1; + + // SDM: store the user mode registers, when in priviledged mode + if ( {instruction[22:20]} == 3'b100 ) + o_user_mode_regs_store_nxt = 1'd1; + end + end + + + // third cycle of multiple load or store + if ( control_state == MTRANS_EXEC2 ) + begin + address_sel_nxt = 4'd5; // o_address + pc_wen_nxt = 1'd0; // hold current PC value + data_access_exec_nxt = 1'd1; // indicate that its a data read or write, + // rather than an instruction fetch + barrel_shift_data_sel_nxt = 2'd1; // load word from memory + + // Load or Store + if ( instruction[20] ) // Load + begin + // Can never be loading the PC in this state, as the PC is always + // the last register in the set to be loaded + if ( !dabt ) + reg_bank_wsel_nxt = mtrans_reg_d2; + end + else // Store + write_data_wen_nxt = 1'd1; + + // LDM: load into user mode registers, when in priviledged mode + if ( {instruction[22],instruction[20],mtrans_r15} == 3'b110 ) + user_mode_regs_load_nxt = 1'd1; + + // SDM: store the user mode registers, when in priviledged mode + if ( {instruction[22],instruction[20]} == 2'b10 ) + o_user_mode_regs_store_nxt = 1'd1; + end + + + // second or fourth cycle of multiple load or store + if ( control_state == MTRANS_EXEC3 && instruction_execute ) + begin + address_sel_nxt = 4'd3; // pc (not pc + 4) + pc_wen_nxt = 1'd0; // hold current PC value + barrel_shift_data_sel_nxt = 2'd1; // load word from memory + + // Can never be loading the PC in this state, as the PC is always + // the last register in the set to be loaded + if ( instruction[20] && !dabt ) // Load + reg_bank_wsel_nxt = mtrans_reg_d2; + + // LDM: load into user mode registers, when in priviledged mode + if ( {instruction[22],instruction[20],mtrans_r15} == 3'b110 ) + user_mode_regs_load_nxt = 1'd1; + + // SDM: store the user mode registers, when in priviledged mode + //if ( {instruction[22:20]} == 3'b100 ) + if ( {instruction[22],instruction[20]} == 2'b10 ) + o_user_mode_regs_store_nxt = 1'd1; + end + + // state is used for LMD/STM of a single register + if ( control_state == MTRANS_EXEC3B && instruction_execute ) + begin + // Save the next instruction to execute later + // Do this even if this instruction does not execute because of Condition + pre_fetch_instruction_wen = 1'd1; + + address_sel_nxt = 4'd3; // pc (not pc + 4) + pc_wen_nxt = 1'd0; // hold current PC value + + // LDM: load into user mode registers, when in priviledged mode + if ( {instruction[22],instruction[20],mtrans_r15} == 3'b110 ) + user_mode_regs_load_nxt = 1'd1; + + // SDM: store the user mode registers, when in priviledged mode + if ( {instruction[22],instruction[20]} == 2'b10 ) + o_user_mode_regs_store_nxt = 1'd1; + end + + if ( control_state == MTRANS_EXEC4 ) + begin + barrel_shift_data_sel_nxt = 2'd1; // load word from memory + + if ( instruction[20] ) // Load + begin + if (!dabt) // dont overwrite registers or status if theres a data abort + begin + if ( mtrans_reg_d2 == 4'd15 ) // load new value into PC + begin + address_sel_nxt = 4'd1; // alu_out - read instructions using new PC value + pc_sel_nxt = 2'd1; // alu_out + pc_wen_nxt = 1'd1; // write PC + + // ldm with S bit and pc: the Status bits are updated + // Node this must be done only at the end + // so the register set is the set in the mode before it + // gets changed. + if ( instruction[22] ) + begin + status_bits_sel_nxt = 3'd1; // alu out + status_bits_flags_wen_nxt = 1'd1; + + // Can't change the mode or mask bits in User mode + if ( i_execute_status_bits[1:0] != USR ) + begin + status_bits_mode_wen_nxt = 1'd1; + status_bits_irq_mask_wen_nxt = 1'd1; + status_bits_firq_mask_wen_nxt = 1'd1; + end + end + end + else + begin + reg_bank_wsel_nxt = mtrans_reg_d2; + end + end + end + + // we have a data abort interrupt + if ( dabt ) + begin + pc_wen_nxt = 1'd0; // hold current PC value + end + + // LDM: load into user mode registers, when in priviledged mode + if ( {instruction[22],instruction[20],mtrans_r15} == 3'b110 ) + user_mode_regs_load_nxt = 1'd1; + + // SDM: store the user mode registers, when in priviledged mode + if ( {instruction[22],instruction[20]} == 2'b10 ) + o_user_mode_regs_store_nxt = 1'd1; + end + + + // state is for when a data abort interrupt is triggered during an LDM + if ( control_state == MTRANS5_ABORT ) + begin + // Restore the Base Address, if the base register is included in the + // list of registers being loaded + if (restore_base_address) // LDM with base address in register list + begin + reg_write_sel_nxt = 3'd6; // write base_register + reg_bank_wsel_nxt = instruction[19:16]; // to Rn + end + end + + + // Multiply or Multiply-Accumulate + if ( control_state == MULT_PROC1 && instruction_execute ) + begin + // Save the next instruction to execute later + // Do this even if this instruction does not execute because of Condition + pre_fetch_instruction_wen = 1'd1; + pc_wen_nxt = 1'd0; // hold current PC value + multiply_function_nxt = o_multiply_function; + end + + + // Multiply or Multiply-Accumulate + // Do multiplication + // Wait for done or accumulate signal + if ( control_state == MULT_PROC2 ) + begin + // Save the next instruction to execute later + // Do this even if this instruction does not execute because of Condition + pc_wen_nxt = 1'd0; // hold current PC value + address_sel_nxt = 4'd3; // pc (not pc + 4) + multiply_function_nxt = o_multiply_function; + end + + + // Save RdLo + // always last cycle of all multiply or multiply accumulate operations + if ( control_state == MULT_STORE ) + begin + reg_write_sel_nxt = 3'd2; // multiply_out + multiply_function_nxt = o_multiply_function; + + if ( itype == MULT ) // 32-bit + reg_bank_wsel_nxt = instruction[19:16]; // Rd + else // 64-bit / Long + reg_bank_wsel_nxt = instruction[15:12]; // RdLo + + if ( instruction[20] ) // the 'S' bit + begin + status_bits_sel_nxt = 3'd4; // { multiply_flags, status_bits_flags[1:0] } + status_bits_flags_wen_nxt = 1'd1; + end + end + + // Add lower 32 bits to multiplication product + if ( control_state == MULT_ACCUMU ) + begin + multiply_function_nxt = o_multiply_function; + pc_wen_nxt = 1'd0; // hold current PC value + address_sel_nxt = 4'd3; // pc (not pc + 4) + end + + // swp - do write request in 2nd cycle + if ( control_state == SWAP_WRITE && instruction_execute ) + begin + barrel_shift_data_sel_nxt = 2'd2; // Shift value from Rm register + address_sel_nxt = 4'd4; // Rn + write_data_wen_nxt = 1'd1; + data_access_exec_nxt = 1'd1; // indicate that its a data read or write, + // rather than an instruction fetch + + if ( instruction[22] ) + byte_enable_sel_nxt = 2'd1; // Save byte + + if ( instruction_execute ) // conditional execution state + pc_wen_nxt = 1'd0; // hold current PC value + + // Save the next instruction to execute later + // Do this even if this instruction does not execute because of Condition + pre_fetch_instruction_wen = 1'd1; + + end + + + // swp - receive read response in 3rd cycle + if ( control_state == SWAP_WAIT1 ) + begin + barrel_shift_data_sel_nxt = 2'd1; // load word from memory + barrel_shift_amount_sel_nxt = 2'd3; // shift by address[1:0] x 8 + + // shift needed + if ( i_execute_address[1:0] != 2'd0 ) + barrel_shift_function_nxt = ROR; + + if ( instruction_execute ) // conditional execution state + begin + address_sel_nxt = 4'd3; // pc (not pc + 4) + pc_wen_nxt = 1'd0; // hold current PC value + end + + // load a byte + if ( instruction[22] ) + alu_out_sel_nxt = 4'd3; // zero_extend8 + + if ( !dabt ) + begin + // Check is the load destination is the PC + if ( instruction[15:12] == 4'd15 ) + begin + pc_sel_nxt = 2'd1; // alu_out + address_sel_nxt = 4'd1; // alu_out + end + else + reg_bank_wsel_nxt = instruction[15:12]; + end + end + + // 1 cycle delay for Co-Processor Register access + if ( control_state == COPRO_WAIT && instruction_execute ) + begin + pre_fetch_instruction_wen = 1'd1; + + if ( instruction[20] ) // mrc instruction + begin + // Check is the load destination is the PC + if ( instruction[15:12] == 4'd15 ) + begin + // If r15 is specified for , the condition code flags are + // updated instead of a general-purpose register. + status_bits_sel_nxt = 3'd3; // i_copro_data + status_bits_flags_wen_nxt = 1'd1; + + // Can't change these in USR mode + if ( i_execute_status_bits[1:0] != USR ) + begin + status_bits_mode_wen_nxt = 1'd1; + status_bits_irq_mask_wen_nxt = 1'd1; + status_bits_firq_mask_wen_nxt = 1'd1; + end + end + else + reg_bank_wsel_nxt = instruction[15:12]; + + reg_write_sel_nxt = 3'd5; // i_copro_data + end + else // mcr instruction + begin + copro_operation_nxt = 2'd2; // Register transfer to Co-Processor + end + end + + + // Have just changed the status_bits mode but this + // creates a 1 cycle gap with the old mode + // coming back from execute into instruction_decode + // So squash that old mode value during this + // cycle of the interrupt transition + if ( control_state == INT_WAIT1 ) + status_bits_mode_nxt = o_status_bits_mode; // Supervisor mode + + end + + +// Speed up the long path from u_decode/o_read_data to u_register_bank/r8_firq +// This pre-encodes the firq_s3 signal thats used in u_register_bank +assign firq_not_user_mode_nxt = !user_mode_regs_load_nxt && status_bits_mode_nxt == FIRQ; + + +// ======================================================== +// Next State Logic +// ======================================================== + +// this replicates the current value of the execute signal in the execute stage +assign instruction_execute = conditional_execute ( o_condition, i_execute_status_bits[31:28] ); + +assign instruction_valid = (control_state == EXECUTE || control_state == PRE_FETCH_EXEC) || + // when last instruction was multi-cycle instruction but did not execute + // because condition was false then act like you're in the execute state + (!instruction_execute && (control_state == PC_STALL1 || + control_state == MEM_WAIT1 || + control_state == COPRO_WAIT || + control_state == SWAP_WRITE || + control_state == MULT_PROC1 || + control_state == MTRANS_EXEC1 || + control_state == MTRANS_EXEC3 || + control_state == MTRANS_EXEC3B ) ); + + + always @* + begin + // default is to hold the current state + control_state_nxt = control_state; + + // Note: The order is important here + if ( control_state == RST_WAIT1 ) control_state_nxt = RST_WAIT2; + if ( control_state == RST_WAIT2 ) control_state_nxt = EXECUTE; + if ( control_state == INT_WAIT1 ) control_state_nxt = INT_WAIT2; + if ( control_state == INT_WAIT2 ) control_state_nxt = EXECUTE; + if ( control_state == COPRO_WAIT ) control_state_nxt = PRE_FETCH_EXEC; + if ( control_state == PC_STALL1 ) control_state_nxt = PC_STALL2; + if ( control_state == PC_STALL2 ) control_state_nxt = EXECUTE; + if ( control_state == SWAP_WRITE ) control_state_nxt = SWAP_WAIT1; + if ( control_state == SWAP_WAIT1 ) control_state_nxt = SWAP_WAIT2; + if ( control_state == MULT_STORE ) control_state_nxt = PRE_FETCH_EXEC; + if ( control_state == MTRANS5_ABORT ) control_state_nxt = PRE_FETCH_EXEC; + + if ( control_state == MEM_WAIT1 ) + control_state_nxt = MEM_WAIT2; + + if ( control_state == MEM_WAIT2 || + control_state == SWAP_WAIT2 ) + begin + if ( write_pc ) // writing to the PC!! + control_state_nxt = PC_STALL1; + else + control_state_nxt = PRE_FETCH_EXEC; + end + + if ( control_state == MTRANS_EXEC1 ) + begin + if (mtrans_instruction_nxt[15:0] != 16'd0) + control_state_nxt = MTRANS_EXEC2; + else // if the register list holds a single register + control_state_nxt = MTRANS_EXEC3; + end + + // Stay in State MTRANS_EXEC2 until the full list of registers to + // load or store has been processed + if ( control_state == MTRANS_EXEC2 && mtrans_num_registers == 5'd1 ) + control_state_nxt = MTRANS_EXEC3; + + if ( control_state == MTRANS_EXEC3 ) control_state_nxt = MTRANS_EXEC4; + + if ( control_state == MTRANS_EXEC3B ) control_state_nxt = MTRANS_EXEC4; + + if ( control_state == MTRANS_EXEC4 ) + begin + if ( dabt ) // data abort + control_state_nxt = MTRANS5_ABORT; + else if (write_pc) // writing to the PC!! + control_state_nxt = PC_STALL1; + else + control_state_nxt = PRE_FETCH_EXEC; + end + + if ( control_state == MULT_PROC1 ) + begin + if (!instruction_execute) + control_state_nxt = PRE_FETCH_EXEC; + else + control_state_nxt = MULT_PROC2; + end + + if ( control_state == MULT_PROC2 ) + begin + if ( i_multiply_done ) + if ( o_multiply_function[1] ) // Accumulate ? + control_state_nxt = MULT_ACCUMU; + else + control_state_nxt = MULT_STORE; + end + + + if ( control_state == MULT_ACCUMU ) + begin + control_state_nxt = MULT_STORE; + end + + + // This should come at the end, so that conditional execution works + // correctly + if ( instruction_valid ) + begin + // default is to stay in execute state, or to move into this + // state from a conditional execute state + control_state_nxt = EXECUTE; + + if ( mem_op ) // load or store word or byte + control_state_nxt = MEM_WAIT1; + if ( write_pc ) + control_state_nxt = PC_STALL1; + if ( itype == MTRANS ) + begin + if ( mtrans_num_registers != 5'd0 ) + begin + // check for LDM/STM of a single register + if ( mtrans_num_registers == 5'd1 ) + control_state_nxt = MTRANS_EXEC3B; + else + control_state_nxt = MTRANS_EXEC1; + end + else + control_state_nxt = MTRANS_EXEC3; + end + + if ( itype == MULT ) + control_state_nxt = MULT_PROC1; + + if ( itype == SWAP ) + control_state_nxt = SWAP_WRITE; + + if ( itype == CORTRANS && !und_request ) + control_state_nxt = COPRO_WAIT; + + // interrupt overrides everything else so its last + if ( interrupt ) + control_state_nxt = INT_WAIT1; + end + end + + +// ======================================================== +// Register Update +// ======================================================== +always @ ( posedge i_clk ) + if (!i_fetch_stall | i_fetch_abort) + begin + o_read_data <= i_read_data; + o_read_data_alignment <= {i_execute_address[1:0], 3'd0}; + abt_address_reg <= i_execute_address; + iabt_reg <= i_iabt; + adex_reg <= i_adex; + abt_status_reg <= i_abt_status; + o_status_bits_mode <= status_bits_mode_nxt; + o_status_bits_irq_mask <= status_bits_irq_mask_nxt; + o_status_bits_firq_mask <= status_bits_firq_mask_nxt; + o_imm32 <= imm32_nxt; + o_imm_shift_amount <= imm_shift_amount_nxt; + o_shift_imm_zero <= shift_imm_zero_nxt; + + // when have an interrupt, execute the interrupt operation + // unconditionally in the execute stage + // ensures that status_bits register gets updated correctly + // Likewise when in middle of multi-cycle instructions + // execute them unconditionally + o_condition <= i_fetch_abort ? NV : // dont execute if there was an abort. + instruction_valid && !interrupt ? condition_nxt : AL; + o_exclusive_exec <= exclusive_exec_nxt; + o_data_access_exec <= data_access_exec_nxt; + + o_rm_sel <= o_rm_sel_nxt; + o_rds_sel <= o_rds_sel_nxt; + o_rn_sel <= o_rn_sel_nxt; + o_barrel_shift_amount_sel <= barrel_shift_amount_sel_nxt; + o_barrel_shift_data_sel <= barrel_shift_data_sel_nxt; + o_barrel_shift_function <= barrel_shift_function_nxt; + o_alu_function <= alu_function_nxt; + o_use_carry_in <= use_carry_in_nxt; + o_multiply_function <= multiply_function_nxt; + o_interrupt_vector_sel <= next_interrupt; + o_address_sel <= address_sel_nxt; + o_pc_sel <= pc_sel_nxt; + o_writeback_sel <= writeback_sel_nxt; + o_byte_enable_sel <= byte_enable_sel_nxt; + o_status_bits_sel <= status_bits_sel_nxt; + o_reg_write_sel <= reg_write_sel_nxt; + o_user_mode_regs_load <= user_mode_regs_load_nxt; + o_firq_not_user_mode <= firq_not_user_mode_nxt; + o_write_data_wen <= write_data_wen_nxt; + o_base_address_wen <= base_address_wen_nxt; + o_pc_wen <= pc_wen_nxt; + o_reg_bank_wsel <= reg_bank_wsel_nxt; + o_reg_bank_wen <= decode ( reg_bank_wsel_nxt ); + o_status_bits_flags_wen <= status_bits_flags_wen_nxt; + o_status_bits_mode_wen <= status_bits_mode_wen_nxt; + o_status_bits_irq_mask_wen <= status_bits_irq_mask_wen_nxt; + o_status_bits_firq_mask_wen <= status_bits_firq_mask_wen_nxt; + + o_copro_opcode1 <= instruction[23:21]; + o_copro_opcode2 <= instruction[7:5]; + o_copro_crn <= instruction[19:16]; + o_copro_crm <= instruction[3:0]; + o_copro_num <= instruction[11:8]; + o_copro_operation <= copro_operation_nxt; + o_copro_write_data_wen <= copro_write_data_wen_nxt; + mtrans_r15 <= mtrans_r15_nxt; + restore_base_address <= restore_base_address_nxt; + control_state <= control_state_nxt; + mtrans_reg_d1 <= mtrans_reg; + mtrans_reg_d2 <= mtrans_reg_d1; + end + + + +always @ ( posedge i_clk ) + if ( !i_fetch_stall ) + begin + // sometimes this is a pre-fetch instruction + // e.g. two ldr instructions in a row. The second ldr will be saved + // to the pre-fetch instruction register + // then when its decoded, a copy is saved to the saved_current_instruction + // register + if (itype == MTRANS) + begin + saved_current_instruction <= mtrans_instruction_nxt; + saved_current_instruction_iabt <= instruction_iabt; + saved_current_instruction_adex <= instruction_adex; + saved_current_instruction_address <= instruction_address; + saved_current_instruction_iabt_status <= instruction_iabt_status; + end + else if (saved_current_instruction_wen) + begin + saved_current_instruction <= instruction; + saved_current_instruction_iabt <= instruction_iabt; + saved_current_instruction_adex <= instruction_adex; + saved_current_instruction_address <= instruction_address; + saved_current_instruction_iabt_status <= instruction_iabt_status; + end + + if (pre_fetch_instruction_wen) + begin + pre_fetch_instruction <= o_read_data; + pre_fetch_instruction_iabt <= iabt_reg; + pre_fetch_instruction_adex <= adex_reg; + pre_fetch_instruction_address <= abt_address_reg; + pre_fetch_instruction_iabt_status <= abt_status_reg; + end + end + + + +always @ ( posedge i_clk ) + if ( !i_fetch_stall | i_dabt ) + begin + irq <= i_irq; + firq <= i_firq; + + if ( control_state == INT_WAIT1 && o_status_bits_mode == SVC ) + begin + dabt_reg <= 1'd0; + end + else + begin + dabt_reg <= dabt_reg || i_dabt; + end + + end + +assign dabt = dabt_reg || i_dabt; + + +// ======================================================== +// Decompiler for debugging core - not synthesizable +// ======================================================== +//synopsys translate_off + +`include "debug_functions.v" + +a23_decompile u_decompile ( + .i_clk ( i_clk ), + .i_fetch_stall ( i_fetch_stall ), + .i_instruction ( instruction ), + .i_instruction_valid ( instruction_valid ), + .i_instruction_execute ( instruction_execute ), + .i_instruction_address ( instruction_address ), + .i_interrupt ( {3{interrupt}} & next_interrupt ), + .i_interrupt_state ( control_state == INT_WAIT2 ), + .i_instruction_undefined ( und_request ), + .i_pc_sel ( o_pc_sel ), + .i_pc_wen ( o_pc_wen ) +); + + +wire [(15*8)-1:0] xCONTROL_STATE; +wire [(15*8)-1:0] xMODE; + +assign xCONTROL_STATE = + control_state == RST_WAIT1 ? "RST_WAIT1" : + control_state == RST_WAIT2 ? "RST_WAIT2" : + + + control_state == INT_WAIT1 ? "INT_WAIT1" : + control_state == INT_WAIT2 ? "INT_WAIT2" : + control_state == EXECUTE ? "EXECUTE" : + control_state == PRE_FETCH_EXEC ? "PRE_FETCH_EXEC" : + control_state == MEM_WAIT1 ? "MEM_WAIT1" : + control_state == MEM_WAIT2 ? "MEM_WAIT2" : + control_state == PC_STALL1 ? "PC_STALL1" : + control_state == PC_STALL2 ? "PC_STALL2" : + control_state == MTRANS_EXEC1 ? "MTRANS_EXEC1" : + control_state == MTRANS_EXEC2 ? "MTRANS_EXEC2" : + control_state == MTRANS_EXEC3 ? "MTRANS_EXEC3" : + control_state == MTRANS_EXEC3B ? "MTRANS_EXEC3B" : + control_state == MTRANS_EXEC4 ? "MTRANS_EXEC4" : + control_state == MTRANS5_ABORT ? "MTRANS5_ABORT" : + control_state == MULT_PROC1 ? "MULT_PROC1" : + control_state == MULT_PROC2 ? "MULT_PROC2" : + control_state == MULT_STORE ? "MULT_STORE" : + control_state == MULT_ACCUMU ? "MULT_ACCUMU" : + control_state == SWAP_WRITE ? "SWAP_WRITE" : + control_state == SWAP_WAIT1 ? "SWAP_WAIT1" : + control_state == SWAP_WAIT2 ? "SWAP_WAIT2" : + control_state == COPRO_WAIT ? "COPRO_WAIT" : + "UNKNOWN " ; + +assign xMODE = mode_name ( o_status_bits_mode ); + +always @( posedge i_clk ) + if (control_state == EXECUTE && ((instruction[0] === 1'bx) || (instruction[31] === 1'bx))) + begin + //`TB_ERROR_MESSAGE + $display("Instruction with x's =%08h", instruction); + end +//synopsys translate_on + +initial begin + + o_read_data = 1'd0; + o_read_data_alignment = 1'd0; // 2 LSBs of read address used for calculating shift in LDRB ops + o_imm32 = 32'd0; + o_imm_shift_amount = 5'd0; + o_shift_imm_zero = 1'd0; + o_condition = 4'he; // 4'he = al + o_exclusive_exec = 1'd0; // exclusive access request ( swap instruction ) + o_data_access_exec = 1'd0; // high means the memory access is a read + o_status_bits_mode = 2'b11; // SVC + o_status_bits_irq_mask = 1'd1; + o_status_bits_firq_mask = 1'd1; + o_rm_sel = 4'd0; + o_rds_sel = 4'd0; + o_rn_sel = 4'd0; + o_barrel_shift_amount_sel = 2'd0; + o_barrel_shift_data_sel = 2'd0; + o_barrel_shift_function = 2'd0; + o_alu_function = 9'd0; + o_use_carry_in = 1'd0; + o_multiply_function = 2'd0; + o_interrupt_vector_sel = 3'd0; + o_address_sel = 4'd2; + o_pc_sel = 2'd2; + o_byte_enable_sel = 2'd0; // byte; halfword or word write + o_status_bits_sel = 3'd0; + o_write_data_wen = 1'd0; + o_base_address_wen = 1'd0; // save LDM base address register + o_pc_wen = 1'd1; + o_writeback_sel = 1'd0; // force supervisor mode off for the memory cycle. + o_reg_bank_wen = 15'd0; + o_reg_bank_wsel = 4'd0; + o_status_bits_flags_wen = 1'd0; + o_status_bits_mode_wen = 1'd0; + o_status_bits_irq_mask_wen = 1'd0; + o_status_bits_firq_mask_wen = 1'd0; + o_copro_opcode1 = 3'd0; + o_copro_opcode2 = 3'd0; + o_copro_crn = 4'd0; + o_copro_crm = 4'd0; + o_copro_num = 4'd0; + o_copro_operation = 2'd0; // 0 = no operation; + o_copro_write_data_wen = 1'd0; + +end +endmodule + + diff --git a/amber/a23_decompile.v b/amber/a23_decompile.v new file mode 100644 index 0000000..1b70993 --- /dev/null +++ b/amber/a23_decompile.v @@ -0,0 +1,916 @@ +////////////////////////////////////////////////////////////////// +// // +// Decompiler for Amber 2 Core // +// // +// This file is part of the Amber project // +// http://www.opencores.org/project,amber // +// // +// Description // +// Decompiler for debugging core - not synthesizable // +// Shows instruction in Execute Stage at last clock of // +// the instruction // +// // +// Author(s): // +// - Conor Santifort, csantifort.amber@gmail.com // +// // +////////////////////////////////////////////////////////////////// +// // +// Copyright (C) 2010 Authors and OPENCORES.ORG // +// // +// This source file may be used and distributed without // +// restriction provided that this copyright statement is not // +// removed from the file and that any derivative work contains // +// the original copyright notice and the associated disclaimer. // +// // +// This source file is free software; you can redistribute it // +// and/or modify it under the terms of the GNU Lesser General // +// Public License as published by the Free Software Foundation; // +// either version 2.1 of the License, or (at your option) any // +// later version. // +// // +// This source 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 Lesser General Public License for more // +// details. // +// // +// You should have received a copy of the GNU Lesser General // +// Public License along with this source; if not, download it // +// from http://www.opencores.org/lgpl.shtml // +// // +////////////////////////////////////////////////////////////////// +`include "global_defines.v" +`include "a23_config_defines.v" + + +module a23_decompile +( +input i_clk, +input i_fetch_stall, +input [31:0] i_instruction, +input i_instruction_valid, +input i_instruction_undefined, +input i_instruction_execute, +input [2:0] i_interrupt, // non-zero value means interrupt triggered +input i_interrupt_state, +input [31:0] i_instruction_address, +input [1:0] i_pc_sel, +input i_pc_wen + +); + +`include "a23_localparams.v" +`include "a23_functions.v" +`ifdef A23_DECOMPILE + +integer i; + +wire [31:0] imm32; +wire [7:0] imm8; +wire [11:0] offset12; +wire [7:0] offset8; +wire [3:0] reg_n, reg_d, reg_m, reg_s; +wire [4:0] shift_imm; +wire [3:0] opcode; +wire [3:0] condition; +wire [3:0] itype; +wire opcode_compare; +wire opcode_move; +wire no_shift; +wire shift_op_imm; +wire [1:0] mtrans_itype; +wire s_bit; + +reg [(5*8)-1:0] xINSTRUCTION_EXECUTE; +reg [(5*8)-1:0] xINSTRUCTION_EXECUTE_R = "--- "; +wire [(8*8)-1:0] TYPE_NAME; +reg [3:0] fchars; +reg [31:0] execute_address = 'd0; +reg [2:0] interrupt_d1; +reg [31:0] execute_instruction = 'd0; +reg execute_now = 'd0; +reg execute_valid = 'd0; +reg execute_undefined = 'd0; + + +// ======================================================== +// Delay instruction to Execute stage +// ======================================================== +always @( posedge i_clk ) + if ( !i_fetch_stall && i_instruction_valid ) + begin + execute_instruction <= i_instruction; + execute_address <= i_instruction_address; + execute_undefined <= i_instruction_undefined; + execute_now <= 1'd1; + end + else + execute_now <= 1'd0; + + +always @ ( posedge i_clk ) + if ( !i_fetch_stall ) + execute_valid <= i_instruction_valid; + +// ======================================================== +// Open File +// ======================================================== +integer decompile_file; + +initial + #1 decompile_file = $fopen(`A23_DECOMPILE_FILE, "w"); + + +// ======================================================== +// Fields within the instruction +// ======================================================== +assign opcode = execute_instruction[24:21]; +assign condition = execute_instruction[31:28]; +assign s_bit = execute_instruction[20]; +assign reg_n = execute_instruction[19:16]; +assign reg_d = execute_instruction[15:12]; +assign reg_m = execute_instruction[3:0]; +assign reg_s = execute_instruction[11:8]; +assign shift_imm = execute_instruction[11:7]; +assign offset12 = execute_instruction[11:0]; +assign offset8 = {execute_instruction[11:8], execute_instruction[3:0]}; +assign imm8 = execute_instruction[7:0]; + +assign no_shift = execute_instruction[11:4] == 8'h0; +assign mtrans_itype = execute_instruction[24:23]; + + +assign opcode_compare = + opcode == CMP || + opcode == CMN || + opcode == TEQ || + opcode == TST ; + +assign opcode_move = + opcode == MOV || + opcode == MVN ; + +assign shift_op_imm = itype == REGOP && execute_instruction[25] == 1'd1; + +assign imm32 = execute_instruction[11:8] == 4'h0 ? { 24'h0, imm8[7:0] } : + execute_instruction[11:8] == 4'h1 ? { imm8[1:0], 24'h0, imm8[7:2] } : + execute_instruction[11:8] == 4'h2 ? { imm8[3:0], 24'h0, imm8[7:4] } : + execute_instruction[11:8] == 4'h3 ? { imm8[5:0], 24'h0, imm8[7:6] } : + execute_instruction[11:8] == 4'h4 ? { imm8[7:0], 24'h0 } : + execute_instruction[11:8] == 4'h5 ? { 2'h0, imm8[7:0], 22'h0 } : + execute_instruction[11:8] == 4'h6 ? { 4'h0, imm8[7:0], 20'h0 } : + execute_instruction[11:8] == 4'h7 ? { 6'h0, imm8[7:0], 18'h0 } : + execute_instruction[11:8] == 4'h8 ? { 8'h0, imm8[7:0], 16'h0 } : + execute_instruction[11:8] == 4'h9 ? { 10'h0, imm8[7:0], 14'h0 } : + execute_instruction[11:8] == 4'ha ? { 12'h0, imm8[7:0], 12'h0 } : + execute_instruction[11:8] == 4'hb ? { 14'h0, imm8[7:0], 10'h0 } : + execute_instruction[11:8] == 4'hc ? { 16'h0, imm8[7:0], 8'h0 } : + execute_instruction[11:8] == 4'hd ? { 18'h0, imm8[7:0], 6'h0 } : + execute_instruction[11:8] == 4'he ? { 20'h0, imm8[7:0], 4'h0 } : + { 22'h0, imm8[7:0], 2'h0 } ; + + +// ======================================================== +// Instruction decode +// ======================================================== +// the order of these matters +assign itype = + {execute_instruction[27:23], execute_instruction[21:20], execute_instruction[11:4] } == { 5'b00010, 2'b00, 8'b00001001 } ? SWAP : // Before REGOP + {execute_instruction[27:22], execute_instruction[7:4] } == { 6'b000000, 4'b1001 } ? MULT : // Before REGOP + {execute_instruction[27:26] } == { 2'b00 } ? REGOP : + {execute_instruction[27:26] } == { 2'b01 } ? TRANS : + {execute_instruction[27:25] } == { 3'b100 } ? MTRANS : + {execute_instruction[27:25] } == { 3'b101 } ? BRANCH : + {execute_instruction[27:25] } == { 3'b110 } ? CODTRANS : + {execute_instruction[27:24], execute_instruction[4] } == { 4'b1110, 1'b0 } ? COREGOP : + {execute_instruction[27:24], execute_instruction[4] } == { 4'b1110, 1'b1 } ? CORTRANS : + SWI ; + + +// +// Convert some important signals to ASCII +// so their values can easily be displayed on a waveform viewer +// +assign TYPE_NAME = itype == REGOP ? "REGOP " : + itype == MULT ? "MULT " : + itype == SWAP ? "SWAP " : + itype == TRANS ? "TRANS " : + itype == MTRANS ? "MTRANS " : + itype == BRANCH ? "BRANCH " : + itype == CODTRANS ? "CODTRANS" : + itype == COREGOP ? "COREGOP " : + itype == CORTRANS ? "CORTRANS" : + itype == SWI ? "SWI " : + "UNKNOWN " ; + +reg [63:0] inst_count = 0 ; +reg [63:0] clk_count = 0 ; + + +always @* + begin + + if ( !execute_now ) + begin + xINSTRUCTION_EXECUTE = xINSTRUCTION_EXECUTE_R; + end // stalled + + else if ( itype == REGOP && opcode == ADC ) xINSTRUCTION_EXECUTE = "adc "; + else if ( itype == REGOP && opcode == ADD ) xINSTRUCTION_EXECUTE = "add "; + else if ( itype == REGOP && opcode == AND ) xINSTRUCTION_EXECUTE = "and "; + else if ( itype == BRANCH && execute_instruction[24] == 1'b0 ) xINSTRUCTION_EXECUTE = "b "; + else if ( itype == REGOP && opcode == BIC ) xINSTRUCTION_EXECUTE = "bic "; + else if ( itype == BRANCH && execute_instruction[24] == 1'b1 ) xINSTRUCTION_EXECUTE = "bl "; + else if ( itype == COREGOP ) xINSTRUCTION_EXECUTE = "cdp "; + else if ( itype == REGOP && opcode == CMN ) xINSTRUCTION_EXECUTE = "cmn "; + else if ( itype == REGOP && opcode == CMP ) xINSTRUCTION_EXECUTE = "cmp "; + else if ( itype == REGOP && opcode == EOR ) xINSTRUCTION_EXECUTE = "eor "; + else if ( itype == CODTRANS && execute_instruction[20] == 1'b1 ) xINSTRUCTION_EXECUTE = "ldc "; + else if ( itype == MTRANS && execute_instruction[20] == 1'b1 ) xINSTRUCTION_EXECUTE = "ldm "; + else if ( itype == TRANS && {execute_instruction[22],execute_instruction[20]} == {1'b0, 1'b1} ) xINSTRUCTION_EXECUTE = "ldr "; + else if ( itype == TRANS && {execute_instruction[22],execute_instruction[20]} == {1'b1, 1'b1} ) xINSTRUCTION_EXECUTE = "ldrb "; + else if ( itype == CORTRANS && execute_instruction[20] == 1'b0 ) xINSTRUCTION_EXECUTE = "mcr "; + else if ( itype == MULT && execute_instruction[21] == 1'b1 ) xINSTRUCTION_EXECUTE = "mla "; + else if ( itype == REGOP && opcode == MOV ) xINSTRUCTION_EXECUTE = "mov "; + else if ( itype == CORTRANS && execute_instruction[20] == 1'b1 ) xINSTRUCTION_EXECUTE = "mrc "; + else if ( itype == MULT && execute_instruction[21] == 1'b0 ) xINSTRUCTION_EXECUTE = "mul "; + else if ( itype == REGOP && opcode == MVN ) xINSTRUCTION_EXECUTE = "mvn "; + else if ( itype == REGOP && opcode == ORR ) xINSTRUCTION_EXECUTE = "orr "; + else if ( itype == REGOP && opcode == RSB ) xINSTRUCTION_EXECUTE = "rsb "; + else if ( itype == REGOP && opcode == RSC ) xINSTRUCTION_EXECUTE = "rsc "; + else if ( itype == REGOP && opcode == SBC ) xINSTRUCTION_EXECUTE = "sbc "; + else if ( itype == CODTRANS && execute_instruction[20] == 1'b0 ) xINSTRUCTION_EXECUTE = "stc "; + else if ( itype == MTRANS && execute_instruction[20] == 1'b0 ) xINSTRUCTION_EXECUTE = "stm "; + else if ( itype == TRANS && {execute_instruction[22],execute_instruction[20]} == {1'b0, 1'b0} ) xINSTRUCTION_EXECUTE = "str "; + else if ( itype == TRANS && {execute_instruction[22],execute_instruction[20]} == {1'b1, 1'b0} ) xINSTRUCTION_EXECUTE = "strb "; + else if ( itype == REGOP && opcode == SUB ) xINSTRUCTION_EXECUTE = "sub "; + else if ( itype == SWI ) xINSTRUCTION_EXECUTE = "swi "; + else if ( itype == SWAP && execute_instruction[22] == 1'b0 ) xINSTRUCTION_EXECUTE = "swp "; + else if ( itype == SWAP && execute_instruction[22] == 1'b1 ) xINSTRUCTION_EXECUTE = "swpb "; + else if ( itype == REGOP && opcode == TEQ ) xINSTRUCTION_EXECUTE = "teq "; + else if ( itype == REGOP && opcode == TST ) xINSTRUCTION_EXECUTE = "tst "; + else xINSTRUCTION_EXECUTE = "unkow"; + end + +always @ ( posedge i_clk ) + xINSTRUCTION_EXECUTE_R <= xINSTRUCTION_EXECUTE; + +always @( posedge i_clk ) + if ( execute_now ) + begin + + clk_count <= clk_count + 'd1; + // Interrupts override instructions that are just starting + if ( interrupt_d1 == 3'd0 || interrupt_d1 == 3'd7 ) + begin + $fwrite(decompile_file,"%09d ", clk_count); + + // Right justify the address + if ( execute_address < 32'h10) $fwrite(decompile_file," %01x: ", {execute_address[ 3:1], 1'd0}); + else if ( execute_address < 32'h100) $fwrite(decompile_file," %02x: ", {execute_address[ 7:1], 1'd0}); + else if ( execute_address < 32'h1000) $fwrite(decompile_file," %03x: ", {execute_address[11:1], 1'd0}); + else if ( execute_address < 32'h10000) $fwrite(decompile_file," %04x: ", {execute_address[15:1], 1'd0}); + else if ( execute_address < 32'h100000) $fwrite(decompile_file," %05x: ", {execute_address[19:1], 1'd0}); + else if ( execute_address < 32'h1000000) $fwrite(decompile_file," %06x: ", {execute_address[23:1], 1'd0}); + else if ( execute_address < 32'h10000000) $fwrite(decompile_file," %07x: ", {execute_address[27:1], 1'd0}); + else $fwrite(decompile_file,"%8x: ", {execute_address[31:1], 1'd0}); + + // Mark that the instruction is not being executed + // condition field in execute stage allows instruction to execute ? + if (!i_instruction_execute) + begin + $fwrite(decompile_file,"-"); + if ( itype == SWI ) + $display ("Cycle %09d SWI not taken *************", clk_count); + end + else + $fwrite(decompile_file," "); + + // ======================================== + // print the instruction name + // ======================================== + inst_count = inst_count+1; + case (numchars( xINSTRUCTION_EXECUTE )) + 4'd1: $fwrite(decompile_file,"%s", xINSTRUCTION_EXECUTE[39:32] ); + 4'd2: $fwrite(decompile_file,"%s", xINSTRUCTION_EXECUTE[39:24] ); + 4'd3: $fwrite(decompile_file,"%s", xINSTRUCTION_EXECUTE[39:16] ); + 4'd4: $fwrite(decompile_file,"%s", xINSTRUCTION_EXECUTE[39: 8] ); + default: $fwrite(decompile_file,"%s", xINSTRUCTION_EXECUTE[39: 0] ); + endcase + + fchars = 8 - numchars(xINSTRUCTION_EXECUTE); + + // Print the Multiple transfer itype + if (itype == MTRANS ) + begin + w_mtrans_itype; + fchars = fchars - 2; + end + + // Print the s bit + if ( ((itype == REGOP && !opcode_compare) || itype == MULT ) && s_bit == 1'b1 ) + begin + $fwrite(decompile_file,"s"); + fchars = fchars - 1; + end + + // Print the p bit + if ( itype == REGOP && opcode_compare && s_bit == 1'b1 && reg_d == 4'd15 ) + begin + $fwrite(decompile_file,"p"); + fchars = fchars - 1; + end + + // Print the condition code + if ( condition != AL ) + begin + wcond; + fchars = fchars - 2; + end + + // Align spaces after instruction + case ( fchars ) + 4'd0: $fwrite(decompile_file,""); + 4'd1: $fwrite(decompile_file," "); + 4'd2: $fwrite(decompile_file," "); + 4'd3: $fwrite(decompile_file," "); + 4'd4: $fwrite(decompile_file," "); + 4'd5: $fwrite(decompile_file," "); + 4'd6: $fwrite(decompile_file," "); + 4'd7: $fwrite(decompile_file," "); + 4'd8: $fwrite(decompile_file," "); + default: $fwrite(decompile_file," "); + endcase + + // ======================================== + // print the arguments for the instruction + // ======================================== + case ( itype ) + REGOP: regop_args; + TRANS: trans_args; + MTRANS: mtrans_args; + BRANCH: branch_args; + MULT: mult_args; + SWAP: swap_args; + CODTRANS: codtrans_args; + COREGOP: begin + // `TB_ERROR_MESSAGE + $write("Coregop not implemented in decompiler yet\n"); + end + CORTRANS: cortrans_args; + SWI: $fwrite(decompile_file,"#0x%06h", execute_instruction[23:0]); + default: begin + //`TB_ERROR_MESSAGE + $write("Unknown Instruction Type ERROR\n"); + end + endcase + + $fwrite( decompile_file,"\n" ); + end + + // Undefined Instruction Interrupts + if ( i_instruction_execute && execute_undefined ) + begin + $fwrite( decompile_file,"%09d interrupt undefined instruction", clk_count ); + $fwrite( decompile_file,", return addr " ); + $fwrite( decompile_file,"%08x\n", pcf(get_reg_val(5'd21)-4'd4) ); + end + + // Software Interrupt + if ( i_instruction_execute && itype == SWI ) + begin + $fwrite( decompile_file,"%09d interrupt swi", clk_count ); + $fwrite( decompile_file,", return addr " ); + $fwrite( decompile_file,"%08x\n", pcf(get_reg_val(5'd21)-4'd4) ); + end + end + + +always @( posedge i_clk ) + if ( !i_fetch_stall ) + begin + interrupt_d1 <= i_interrupt; + + // Asynchronous Interrupts + if ( interrupt_d1 != 3'd0 && i_interrupt_state ) + begin + $fwrite( decompile_file,"%09d interrupt ", clk_count ); + case ( interrupt_d1 ) + 3'd1: $fwrite( decompile_file,"data abort" ); + 3'd2: $fwrite( decompile_file,"firq" ); + 3'd3: $fwrite( decompile_file,"irq" ); + 3'd4: $fwrite( decompile_file,"address exception" ); + 3'd5: $fwrite( decompile_file,"instruction abort" ); + default: $fwrite( decompile_file,"unknown type" ); + endcase + + $fwrite( decompile_file, "@addr "); + tmp_address = get_32bit_signal(2); + fwrite_hex_drop_zeros(decompile_file, {tmp_address[31:2], 2'd0} ); + + $fwrite( decompile_file,", return addr " ); + + case ( interrupt_d1 ) + 3'd1: $fwrite(decompile_file,"%08h\n", pcf(get_reg_val(5'd16))); + 3'd2: $fwrite(decompile_file,"%08h\n", pcf(get_reg_val(5'd17))); + 3'd3: $fwrite(decompile_file,"%08h\n", pcf(get_reg_val(5'd18))); + 3'd4: $fwrite(decompile_file,"%08h\n", pcf(get_reg_val(5'd19))); + 3'd5: $fwrite(decompile_file,"%08h\n", pcf(get_reg_val(5'd19))); + 3'd7: $fwrite(decompile_file,"%08h\n", pcf(get_reg_val(5'd20))); + default: ; + endcase + end + end + + +// jump +// Dont print a jump message for interrupts +always @( posedge i_clk ) + if ( + i_pc_sel != 2'd0 && + i_pc_wen && + !i_fetch_stall && + i_instruction_execute && + i_interrupt == 3'd0 && + !execute_undefined && + itype != SWI && + execute_address != get_32bit_signal(0) // Don't print jump to same address + ) + begin + $fwrite(decompile_file,"%09d jump from ", clk_count); + fwrite_hex_drop_zeros(decompile_file, pcf(execute_address)); + $fwrite(decompile_file," to "); + fwrite_hex_drop_zeros(decompile_file, pcf(get_32bit_signal(0)) ); // u_execute.pc_nxt + $fwrite(decompile_file,", r0 %08h, ", get_reg_val ( 5'd0 )); + $fwrite(decompile_file,"r1 %08h\n", get_reg_val ( 5'd1 )); + end + +// ================================================================================= +// Memory Writes - Peek into fetch module +// ================================================================================= + +reg [31:0] tmp_address; + + // Data access +always @( posedge i_clk ) + // Data Write + if ( get_1bit_signal(0) && !get_1bit_signal(1) ) + begin + + $fwrite(decompile_file, "%09d write addr ", clk_count); + tmp_address = get_32bit_signal(2); + fwrite_hex_drop_zeros(decompile_file, {tmp_address [31:2], 2'd0} ); + + $fwrite(decompile_file, ", data %08h, be %h", + get_32bit_signal(3), // u_cache.i_write_data + get_4bit_signal (0)); // u_cache.i_byte_enable + + if ( get_1bit_signal(2) ) // Abort! address translation failed + $fwrite(decompile_file, " aborted!\n"); + else + $fwrite(decompile_file, "\n"); + end + + // Data Read + else if (get_1bit_signal(3) && !get_1bit_signal(0) && !get_1bit_signal(1)) + begin + + $fwrite(decompile_file, "%09d read addr ", clk_count); + tmp_address = get_32bit_signal(2); + fwrite_hex_drop_zeros(decompile_file, {tmp_address[31:2], 2'd0} ); + + $fwrite(decompile_file, ", data %08h", get_32bit_signal(4)); // u_decode.i_read_data + + if ( get_1bit_signal(2) ) // Abort! address translation failed + $fwrite(decompile_file, " aborted!\n"); + else + $fwrite(decompile_file, "\n"); + end + + +// ================================================================================= +// Tasks +// ================================================================================= + +// Write Condition field +task wcond; + begin + case( condition) + 4'h0: $fwrite(decompile_file,"eq"); + 4'h1: $fwrite(decompile_file,"ne"); + 4'h2: $fwrite(decompile_file,"cs"); + 4'h3: $fwrite(decompile_file,"cc"); + 4'h4: $fwrite(decompile_file,"mi"); + 4'h5: $fwrite(decompile_file,"pl"); + 4'h6: $fwrite(decompile_file,"vs"); + 4'h7: $fwrite(decompile_file,"vc"); + 4'h8: $fwrite(decompile_file,"hi"); + 4'h9: $fwrite(decompile_file,"ls"); + 4'ha: $fwrite(decompile_file,"ge"); + 4'hb: $fwrite(decompile_file,"lt"); + 4'hc: $fwrite(decompile_file,"gt"); + 4'hd: $fwrite(decompile_file,"le"); + 4'he: $fwrite(decompile_file," "); // Always + default: $fwrite(decompile_file,"nv"); // Never + endcase + end +endtask + +// ldm and stm itypes +task w_mtrans_itype; + begin + case( mtrans_itype ) + 4'h0: $fwrite(decompile_file,"da"); + 4'h1: $fwrite(decompile_file,"ia"); + 4'h2: $fwrite(decompile_file,"db"); + 4'h3: $fwrite(decompile_file,"ib"); + default: $fwrite(decompile_file,"xx"); + endcase + end +endtask + +// e.g. mrc 15, 0, r9, cr0, cr0, {0} +task cortrans_args; + begin + // Co-Processor Number + $fwrite(decompile_file,"%1d, ", execute_instruction[11:8]); + // opcode1 + $fwrite(decompile_file,"%1d, ", execute_instruction[23:21]); + // Rd [15:12] + warmreg(reg_d); + // CRn [19:16] + $fwrite(decompile_file,", cr%1d", execute_instruction[19:16]); + // CRm [3:0] + $fwrite(decompile_file,", cr%1d", execute_instruction[3:0]); + // Opcode2 [7:5] + $fwrite(decompile_file,", {%1d}", execute_instruction[7:5]); + end +endtask + + +// ldc 15, 0, r9, cr0, cr0, {0} +task codtrans_args; + begin + // Co-Processor Number + $fwrite(decompile_file,"%1d, ", execute_instruction[11:8]); + // CRd [15:12] + $fwrite(decompile_file,"cr%1d, ", execute_instruction[15:12]); + // Rd [19:16] + warmreg(reg_n); + end +endtask + + +task branch_args; +reg [31:0] shift_amount; + begin + if (execute_instruction[23]) // negative + shift_amount = {~execute_instruction[23:0] + 24'd1, 2'd0}; + else + shift_amount = {execute_instruction[23:0], 2'd0}; + + if (execute_instruction[23]) // negative + fwrite_hex_drop_zeros ( decompile_file, get_reg_val( 5'd21 ) - shift_amount ); + else + fwrite_hex_drop_zeros ( decompile_file, get_reg_val( 5'd21 ) + shift_amount ); + end +endtask + + +task mult_args; + begin + warmreg(reg_n); // Rd is in the Rn position for MULT instructions + $fwrite(decompile_file,", "); + warmreg(reg_m); + $fwrite(decompile_file,", "); + warmreg(reg_s); + + if (execute_instruction[21]) // MLA + begin + $fwrite(decompile_file,", "); + warmreg(reg_d); + end + end +endtask + + +task swap_args; + begin + warmreg(reg_d); + $fwrite(decompile_file,", "); + warmreg(reg_m); + $fwrite(decompile_file,", ["); + warmreg(reg_n); + $fwrite(decompile_file,"]"); + end +endtask + + +task regop_args; + begin + if (!opcode_compare) + warmreg(reg_d); + + if (!opcode_move ) + begin + if (!opcode_compare) + begin + $fwrite(decompile_file,", "); + if (reg_d < 4'd10 || reg_d > 4'd12) + $fwrite(decompile_file," "); + end + warmreg(reg_n); + $fwrite(decompile_file,", "); + if (reg_n < 4'd10 || reg_n > 4'd12) + $fwrite(decompile_file," "); + end + else + begin + $fwrite(decompile_file,", "); + if (reg_d < 4'd10 || reg_d > 4'd12) + $fwrite(decompile_file," "); + end + + if (shift_op_imm) + begin + if (|imm32[31:15]) + $fwrite(decompile_file,"#0x%08h", imm32); + else + $fwrite(decompile_file,"#%1d", imm32); + end + else // Rm + begin + warmreg(reg_m); + if (execute_instruction[4]) + // Register Shifts + wshiftreg; + else + // Immediate shifts + wshift; + end + end +endtask + + +task trans_args; + begin + warmreg(reg_d); // Destination register + + casez ({execute_instruction[25:23], execute_instruction[21], no_shift, offset12==12'd0}) + 6'b0100?0 : begin $fwrite(decompile_file,", ["); warmreg(reg_n); $fwrite(decompile_file,", #-%1d]" , offset12); end + 6'b0110?0 : begin $fwrite(decompile_file,", ["); warmreg(reg_n); $fwrite(decompile_file,", #%1d]" , offset12); end + 6'b0100?1 : begin $fwrite(decompile_file,", ["); warmreg(reg_n); $fwrite(decompile_file,"]"); end + 6'b0110?1 : begin $fwrite(decompile_file,", ["); warmreg(reg_n); $fwrite(decompile_file,"]"); end + 6'b0101?? : begin $fwrite(decompile_file,", ["); warmreg(reg_n); $fwrite(decompile_file,", #-%1d]!", offset12); end + 6'b0111?? : begin $fwrite(decompile_file,", ["); warmreg(reg_n); $fwrite(decompile_file,", #%1d]!" , offset12); end + + 6'b0000?0 : begin $fwrite(decompile_file,", ["); warmreg(reg_n); $fwrite(decompile_file,"], #-%1d", offset12); end + 6'b0010?0 : begin $fwrite(decompile_file,", ["); warmreg(reg_n); $fwrite(decompile_file,"], #%1d" , offset12); end + 6'b0001?0 : begin $fwrite(decompile_file,", ["); warmreg(reg_n); $fwrite(decompile_file,"], #-%1d", offset12); end + 6'b0011?0 : begin $fwrite(decompile_file,", ["); warmreg(reg_n); $fwrite(decompile_file,"], #%1d" , offset12); end + + 6'b0000?1 : begin $fwrite(decompile_file,", ["); warmreg(reg_n); $fwrite(decompile_file,"]"); end + 6'b0010?1 : begin $fwrite(decompile_file,", ["); warmreg(reg_n); $fwrite(decompile_file,"]"); end + 6'b0001?1 : begin $fwrite(decompile_file,", ["); warmreg(reg_n); $fwrite(decompile_file,"]"); end + 6'b0011?1 : begin $fwrite(decompile_file,", ["); warmreg(reg_n); $fwrite(decompile_file,"]"); end + + 6'b11001? : begin $fwrite(decompile_file,", ["); warmreg(reg_n); $fwrite(decompile_file,", -"); warmreg(reg_m); $fwrite(decompile_file,"]"); end + 6'b11101? : begin $fwrite(decompile_file,", ["); warmreg(reg_n); $fwrite(decompile_file,", "); warmreg(reg_m); $fwrite(decompile_file,"]"); end + 6'b11011? : begin $fwrite(decompile_file,", ["); warmreg(reg_n); $fwrite(decompile_file,", -"); warmreg(reg_m); $fwrite(decompile_file,"]!"); end + 6'b11111? : begin $fwrite(decompile_file,", ["); warmreg(reg_n); $fwrite(decompile_file,", "); warmreg(reg_m); $fwrite(decompile_file,"]!"); end + + 6'b10001? : begin $fwrite(decompile_file,", ["); warmreg(reg_n); $fwrite(decompile_file,"], -"); warmreg(reg_m); end + 6'b10101? : begin $fwrite(decompile_file,", ["); warmreg(reg_n); $fwrite(decompile_file,"], "); warmreg(reg_m); end + 6'b10011? : begin $fwrite(decompile_file,", ["); warmreg(reg_n); $fwrite(decompile_file,"], -"); warmreg(reg_m); end + 6'b10111? : begin $fwrite(decompile_file,", ["); warmreg(reg_n); $fwrite(decompile_file,"], "); warmreg(reg_m); end + + 6'b11000? : begin $fwrite(decompile_file,", ["); warmreg(reg_n); $fwrite(decompile_file,", -"); warmreg(reg_m); wshift; $fwrite(decompile_file,"]"); end + 6'b11100? : begin $fwrite(decompile_file,", ["); warmreg(reg_n); $fwrite(decompile_file,", "); warmreg(reg_m); wshift; $fwrite(decompile_file,"]"); end + 6'b11010? : begin $fwrite(decompile_file,", ["); warmreg(reg_n); $fwrite(decompile_file,", -"); warmreg(reg_m); wshift; $fwrite(decompile_file,"]!");end + 6'b11110? : begin $fwrite(decompile_file,", ["); warmreg(reg_n); $fwrite(decompile_file,", "); warmreg(reg_m); wshift; $fwrite(decompile_file,"]!");end + + 6'b10000? : begin $fwrite(decompile_file,", ["); warmreg(reg_n); $fwrite(decompile_file,"], -"); warmreg(reg_m); wshift; end + 6'b10100? : begin $fwrite(decompile_file,", ["); warmreg(reg_n); $fwrite(decompile_file,"], "); warmreg(reg_m); wshift; end + 6'b10010? : begin $fwrite(decompile_file,", ["); warmreg(reg_n); $fwrite(decompile_file,"], -"); warmreg(reg_m); wshift; end + 6'b10110? : begin $fwrite(decompile_file,", ["); warmreg(reg_n); $fwrite(decompile_file,"], "); warmreg(reg_m); wshift; end + + endcase + end +endtask + + +task mtrans_args; + begin + warmreg(reg_n); + if (execute_instruction[21]) $fwrite(decompile_file,"!"); + $fwrite(decompile_file,", {"); + for (i=0;i<16;i=i+1) + if (execute_instruction[i]) + begin + warmreg(i); + if (more_to_come(execute_instruction[15:0], i)) + $fwrite(decompile_file,", "); + end + $fwrite(decompile_file,"}"); + // SDM: store the user mode registers, when in priviledged mode + if (execute_instruction[22:20] == 3'b100) + $fwrite(decompile_file,"^"); + end +endtask + + +task wshift; + begin + // Check that its a valid shift operation. LSL by #0 is the null operator + if (execute_instruction[6:5] != LSL || shift_imm != 5'd0) + begin + case(execute_instruction[6:5]) + 2'd0: $fwrite(decompile_file,", lsl"); + 2'd1: $fwrite(decompile_file,", lsr"); + 2'd2: $fwrite(decompile_file,", asr"); + 2'd3: if (shift_imm == 5'd0) $fwrite(decompile_file,", rrx"); else $fwrite(decompile_file,", ror"); + endcase + + if (execute_instruction[6:5] != 2'd3 || shift_imm != 5'd0) + $fwrite(decompile_file," #%1d", shift_imm); + end + end +endtask + + +task wshiftreg; + begin + case(execute_instruction[6:5]) + 2'd0: $fwrite(decompile_file,", lsl "); + 2'd1: $fwrite(decompile_file,", lsr "); + 2'd2: $fwrite(decompile_file,", asr "); + 2'd3: $fwrite(decompile_file,", ror "); + endcase + + warmreg(reg_s); + end +endtask + + +task warmreg; +input [3:0] regnum; + begin + if (regnum < 4'd12) + $fwrite(decompile_file,"r%1d", regnum); + else + case (regnum) + 4'd12 : $fwrite(decompile_file,"ip"); + 4'd13 : $fwrite(decompile_file,"sp"); + 4'd14 : $fwrite(decompile_file,"lr"); + 4'd15 : $fwrite(decompile_file,"pc"); + endcase + end +endtask + + +task fwrite_hex_drop_zeros; +input [31:0] file; +input [31:0] num; + begin + if (num[31:28] != 4'd0) + $fwrite(file, "%x", num); + else if (num[27:24] != 4'd0) + $fwrite(file, "%x", num[27:0]); + else if (num[23:20] != 4'd0) + $fwrite(file, "%x", num[23:0]); + else if (num[19:16] != 4'd0) + $fwrite(file, "%x", num[19:0]); + else if (num[15:12] != 4'd0) + $fwrite(file, "%x", num[15:0]); + else if (num[11:8] != 4'd0) + $fwrite(file, "%x", num[11:0]); + else if (num[7:4] != 4'd0) + $fwrite(file, "%x", num[7:0]); + else + $fwrite(file, "%x", num[3:0]); + + end +endtask + + + +// ================================================================================= +// Functions +// ================================================================================= + +// Get current value of register +function [31:0] get_reg_val; +input [4:0] regnum; +begin + case (regnum) + 5'd0 : get_reg_val = `U_REGISTER_BANK.r0_out; + 5'd1 : get_reg_val = `U_REGISTER_BANK.r1_out; + 5'd2 : get_reg_val = `U_REGISTER_BANK.r2_out; + 5'd3 : get_reg_val = `U_REGISTER_BANK.r3_out; + 5'd4 : get_reg_val = `U_REGISTER_BANK.r4_out; + 5'd5 : get_reg_val = `U_REGISTER_BANK.r5_out; + 5'd6 : get_reg_val = `U_REGISTER_BANK.r6_out; + 5'd7 : get_reg_val = `U_REGISTER_BANK.r7_out; + 5'd8 : get_reg_val = `U_REGISTER_BANK.r8_out; + 5'd9 : get_reg_val = `U_REGISTER_BANK.r9_out; + 5'd10 : get_reg_val = `U_REGISTER_BANK.r10_out; + 5'd11 : get_reg_val = `U_REGISTER_BANK.r11_out; + 5'd12 : get_reg_val = `U_REGISTER_BANK.r12_out; + 5'd13 : get_reg_val = `U_REGISTER_BANK.r13_out; + 5'd14 : get_reg_val = `U_REGISTER_BANK.r14_out; + 5'd15 : get_reg_val = `U_REGISTER_BANK.r15_out_rm; // the version of pc with status bits + + 5'd16 : get_reg_val = `U_REGISTER_BANK.r14_svc; + 5'd17 : get_reg_val = `U_REGISTER_BANK.r14_firq; + 5'd18 : get_reg_val = `U_REGISTER_BANK.r14_irq; + 5'd19 : get_reg_val = `U_REGISTER_BANK.r14_svc; + 5'd20 : get_reg_val = `U_REGISTER_BANK.r14_svc; + 5'd21 : get_reg_val = `U_REGISTER_BANK.r15_out_rn; // the version of pc without status bits + endcase +end +endfunction + + +function [31:0] get_32bit_signal; +input [2:0] num; +begin + case (num) + 3'd0: get_32bit_signal = `U_EXECUTE.pc_nxt; + 3'd1: get_32bit_signal = `U_FETCH.i_address; + 3'd2: get_32bit_signal = `U_FETCH.i_address; + 3'd3: get_32bit_signal = `U_CACHE.i_write_data; + 3'd4: get_32bit_signal = `U_DECODE.i_read_data; + endcase +end +endfunction + + +function get_1bit_signal; +input [2:0] num; +begin + case (num) + 3'd0: get_1bit_signal = `U_FETCH.i_write_enable; + 3'd1: get_1bit_signal = `U_AMBER.fetch_stall; + 3'd2: get_1bit_signal = 1'd0; + 3'd3: get_1bit_signal = `U_FETCH.i_data_access; + endcase +end +endfunction + + +function [3:0] get_4bit_signal; +input [2:0] num; +begin + case (num) + 3'd0: get_4bit_signal = `U_CACHE.i_byte_enable; + endcase +end +endfunction + + +function [3:0] numchars; +input [(5*8)-1:0] xINSTRUCTION_EXECUTE; +begin + if (xINSTRUCTION_EXECUTE[31:0] == " ") + numchars = 4'd1; +else if (xINSTRUCTION_EXECUTE[23:0] == " ") + numchars = 4'd2; +else if (xINSTRUCTION_EXECUTE[15:0] == " ") + numchars = 4'd3; +else if (xINSTRUCTION_EXECUTE[7:0] == " ") + numchars = 4'd4; +else + numchars = 4'd5; +end +endfunction + + +function more_to_come; +input [15:0] regs; +input [31:0] i; +begin +case (i) + 15 : more_to_come = 1'd0; + 14 : more_to_come = regs[15] ? 1'd1 : 1'd0; + 13 : more_to_come = |regs[15:14] ? 1'd1 : 1'd0; + 12 : more_to_come = |regs[15:13] ? 1'd1 : 1'd0; + 11 : more_to_come = |regs[15:12] ? 1'd1 : 1'd0; + 10 : more_to_come = |regs[15:11] ? 1'd1 : 1'd0; + 9 : more_to_come = |regs[15:10] ? 1'd1 : 1'd0; + 8 : more_to_come = |regs[15: 9] ? 1'd1 : 1'd0; + 7 : more_to_come = |regs[15: 8] ? 1'd1 : 1'd0; + 6 : more_to_come = |regs[15: 7] ? 1'd1 : 1'd0; + 5 : more_to_come = |regs[15: 6] ? 1'd1 : 1'd0; + 4 : more_to_come = |regs[15: 5] ? 1'd1 : 1'd0; + 3 : more_to_come = |regs[15: 4] ? 1'd1 : 1'd0; + 2 : more_to_come = |regs[15: 3] ? 1'd1 : 1'd0; + 1 : more_to_come = |regs[15: 2] ? 1'd1 : 1'd0; + 0 : more_to_come = |regs[15: 1] ? 1'd1 : 1'd0; +endcase +end +endfunction + +`endif + +endmodule + diff --git a/amber/a23_execute.v b/amber/a23_execute.v new file mode 100644 index 0000000..32eeea1 --- /dev/null +++ b/amber/a23_execute.v @@ -0,0 +1,649 @@ +////////////////////////////////////////////////////////////////// +// // +// Execute stage of Amber 2 Core // +// // +// This file is part of the Amber project // +// http://www.opencores.org/project,amber // +// // +// Description // +// Executes instructions. Instantiates the register file, ALU // +// multiplication unit and barrel shifter. This stage is // +// relitively simple. All the complex stuff is done in the // +// decode stage. // +// // +// Author(s): // +// - Conor Santifort, csantifort.amber@gmail.com // +// // +////////////////////////////////////////////////////////////////// +// // +// Copyright (C) 2010 Authors and OPENCORES.ORG // +// // +// This source file may be used and distributed without // +// restriction provided that this copyright statement is not // +// removed from the file and that any derivative work contains // +// the original copyright notice and the associated disclaimer. // +// // +// This source file is free software; you can redistribute it // +// and/or modify it under the terms of the GNU Lesser General // +// Public License as published by the Free Software Foundation; // +// either version 2.1 of the License, or (at your option) any // +// later version. // +// // +// This source 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 Lesser General Public License for more // +// details. // +// // +// You should have received a copy of the GNU Lesser General // +// Public License along with this source; if not, download it // +// from http://www.opencores.org/lgpl.shtml // +// // +////////////////////////////////////////////////////////////////// + +`include "a23_config_defines.v" + +module a23_execute ( + +input i_clk, +input [31:0] i_read_data, +input [4:0] i_read_data_alignment, // 2 LSBs of address in [4:3], appended + // with 3 zeros +input [31:0] i_copro_read_data, // From Co-Processor, to either Register + // or Memory +input i_data_access_exec, // from Instruction Decode stage + // high means the memory access is a read + // read or write, low for instruction + +output reg [31:0] o_copro_write_data, +output reg [31:0] o_write_data, +output reg [31:0] o_address, +output reg o_adex, // Address Exception +output reg o_address_valid, // Prevents the reset address value being a + // wishbone access +output [31:0] o_address_nxt, // un-registered version of address to the + // cache rams address ports +output reg o_priviledged, // Priviledged access +output reg o_exclusive, // swap access +output reg o_write_enable, +output reg o_translate, +output reg [3:0] o_byte_enable, +output reg o_data_access, // To Fetch stage. high = data fetch, + // low = instruction fetch +output [31:0] o_status_bits, // Full PC will all status bits, but PC part zero'ed out +output o_multiply_done, + + +// -------------------------------------------------- +// Control signals from Instruction Decode stage +// -------------------------------------------------- +input i_fetch_stall, // stall all stages of the cpu at the same time +input i_fetch_abort, // transfer was not possible. +input [1:0] i_status_bits_mode, +input i_status_bits_irq_mask, +input i_status_bits_firq_mask, +input [31:0] i_imm32, +input [4:0] i_imm_shift_amount, +input i_shift_imm_zero, +input [3:0] i_condition, +input i_exclusive_exec, // swap access +input i_use_carry_in, // e.g. add with carry instruction + +input [3:0] i_rm_sel, +input [3:0] i_rds_sel, +input [3:0] i_rn_sel, +input [3:0] i_rm_sel_nxt, +input [3:0] i_rds_sel_nxt, +input [3:0] i_rn_sel_nxt, +input [1:0] i_barrel_shift_amount_sel, +input [1:0] i_barrel_shift_data_sel, +input [1:0] i_barrel_shift_function, +input [8:0] i_alu_function, +input [1:0] i_multiply_function, +input [2:0] i_interrupt_vector_sel, +input [3:0] i_address_sel, +input [1:0] i_pc_sel, +input i_writeback_sel, +input [1:0] i_byte_enable_sel, +input [2:0] i_status_bits_sel, +input [2:0] i_reg_write_sel, +input i_user_mode_regs_load, +input i_user_mode_regs_store_nxt, +input i_firq_not_user_mode, + +input i_write_data_wen, +input i_base_address_wen, // save LDM base address register, + // in case of data abort +input i_pc_wen, +input [14:0] i_reg_bank_wen, +input [3:0] i_reg_bank_wsel, +input i_status_bits_flags_wen, +input i_status_bits_mode_wen, +input i_status_bits_irq_mask_wen, +input i_status_bits_firq_mask_wen, +input i_copro_write_data_wen + +); + +`include "a23_localparams.v" +`include "a23_functions.v" + +// ======================================================== +// Internal signals +// ======================================================== +wire [31:0] write_data_nxt; +wire [3:0] byte_enable_nxt; +wire [31:0] pc_plus4; +wire [31:0] pc_minus4; +wire [31:0] address_plus4; +wire [31:0] alu_plus4; +wire [31:0] rn_plus4; +wire [31:0] alu_out; +wire [3:0] alu_flags; +wire [31:0] rm; +wire [31:0] rs; +wire [31:0] rd; +wire [31:0] rn; +wire [31:0] pc; +wire [31:0] pc_nxt; +wire write_enable_nxt; +wire [31:0] interrupt_vector; +wire [7:0] shift_amount; +wire [31:0] barrel_shift_in; +wire [31:0] barrel_shift_out; +wire barrel_shift_carry; + +wire [3:0] status_bits_flags_nxt; +reg [3:0] status_bits_flags = 'd0; +wire [1:0] status_bits_mode_nxt; +wire [1:0] status_bits_mode_nr; +reg [1:0] status_bits_mode = SVC; + // raw rs select +wire [1:0] status_bits_mode_rds_nxt; +wire [1:0] status_bits_mode_rds_nr; +reg [1:0] status_bits_mode_rds; + // one-hot encoded rs select +wire [3:0] status_bits_mode_rds_oh_nxt; +reg [3:0] status_bits_mode_rds_oh = 1'd1 << OH_SVC; +wire status_bits_mode_rds_oh_update; +wire status_bits_irq_mask_nxt; +reg status_bits_irq_mask = 1'd1; +wire status_bits_firq_mask_nxt; +reg status_bits_firq_mask = 1'd1; + +wire execute; // high when condition execution is true +wire [31:0] reg_write_nxt; +wire pc_wen; +wire [14:0] reg_bank_wen; +wire [3:0] reg_bank_wsel; +wire [31:0] multiply_out; +wire [1:0] multiply_flags; +reg [31:0] base_address = 'd0; // Saves base address during LDM instruction in + // case of data abort + +wire priviledged_nxt; +wire priviledged_update; +wire address_update; +wire base_address_update; +wire write_data_update; +wire copro_write_data_update; +wire translate_update; +wire byte_enable_update; +wire data_access_update; +wire write_enable_update; +wire exclusive_update; +wire status_bits_flags_update; +wire status_bits_mode_update; +wire status_bits_irq_mask_update; +wire status_bits_firq_mask_update; +wire [1:0] status_bits_out; + +wire [31:0] alu_out_pc_filtered; +wire adex_nxt; + +wire carry_in; + + +// ======================================================== +// Status Bits in PC register +// ======================================================== +assign status_bits_out = (i_status_bits_mode_wen && i_status_bits_sel == 3'd1 && execute) ? + alu_out[1:0] : status_bits_mode ; + + +assign o_status_bits = { status_bits_flags, // 31:28 + status_bits_irq_mask, // 7 + status_bits_firq_mask, // 6 + 24'd0, + status_bits_out}; // 1:0 = mode + +// ======================================================== +// Status Bits Select +// ======================================================== +assign status_bits_flags_nxt = i_status_bits_sel == 3'd0 ? alu_flags : + i_status_bits_sel == 3'd1 ? alu_out [31:28] : + i_status_bits_sel == 3'd3 ? i_copro_read_data[31:28] : + // update flags after a multiply operation + i_status_bits_sel == 3'd4 ? { multiply_flags, status_bits_flags[1:0] } : + // regops that do not change the overflow flag + i_status_bits_sel == 3'd5 ? { alu_flags[3:1], status_bits_flags[0] } : + 4'b1111 ; + +assign status_bits_mode_nxt = i_status_bits_sel == 3'd0 ? i_status_bits_mode : + i_status_bits_sel == 3'd5 ? i_status_bits_mode : + i_status_bits_sel == 3'd1 ? alu_out [1:0] : + i_copro_read_data [1:0] ; + + +// Used for the Rds output of register_bank - this special version of +// status_bits_mode speeds up the critical path from status_bits_mode through the +// register_bank, barrel_shifter and alu. It moves a mux needed for the +// i_user_mode_regs_store_nxt signal back into the previous stage - +// so its really part of the decode stage even though the logic is right here +// In addition the signal is one-hot encoded to further speed up the logic +// Raw version is also kept for ram-based register bank implementation. + +assign status_bits_mode_rds_nxt = i_user_mode_regs_store_nxt ? USR : + status_bits_mode_update ? status_bits_mode_nxt : + status_bits_mode ; + +assign status_bits_mode_rds_oh_nxt = oh_status_bits_mode(status_bits_mode_rds_nxt); + + +assign status_bits_irq_mask_nxt = i_status_bits_sel == 3'd0 ? i_status_bits_irq_mask : + i_status_bits_sel == 3'd5 ? i_status_bits_irq_mask : + i_status_bits_sel == 3'd1 ? alu_out [27] : + i_copro_read_data [27] ; + +assign status_bits_firq_mask_nxt = i_status_bits_sel == 3'd0 ? i_status_bits_firq_mask : + i_status_bits_sel == 3'd5 ? i_status_bits_firq_mask : + i_status_bits_sel == 3'd1 ? alu_out [26] : + i_copro_read_data [26] ; + + + +// ======================================================== +// Adders +// ======================================================== +assign pc_plus4 = pc + 32'd4; +assign pc_minus4 = pc - 32'd4; +assign address_plus4 = o_address + 32'd4; +assign alu_plus4 = alu_out + 32'd4; +assign rn_plus4 = rn + 32'd4; + +// ======================================================== +// Barrel Shift Amount Select +// ======================================================== +// An immediate shift value of 0 is translated into 32 +assign shift_amount = i_barrel_shift_amount_sel == 2'd0 ? 8'd0 : + i_barrel_shift_amount_sel == 2'd1 ? rs[7:0] : + i_barrel_shift_amount_sel == 2'd2 ? {3'd0, i_imm_shift_amount } : + {3'd0, i_read_data_alignment } ; + +// ======================================================== +// Barrel Shift Data Select +// ======================================================== +assign barrel_shift_in = i_barrel_shift_data_sel == 2'd0 ? i_imm32 : + i_barrel_shift_data_sel == 2'd1 ? i_read_data : + rm ; + +// ======================================================== +// Interrupt vector Select +// ======================================================== + +assign interrupt_vector = // Reset vector + (i_interrupt_vector_sel == 3'd0) ? 32'h00000000 : + // Data abort interrupt vector + (i_interrupt_vector_sel == 3'd1) ? 32'h00000010 : + // Fast interrupt vector + (i_interrupt_vector_sel == 3'd2) ? 32'h0000001c : + // Regular interrupt vector + (i_interrupt_vector_sel == 3'd3) ? 32'h00000018 : + // Prefetch abort interrupt vector + (i_interrupt_vector_sel == 3'd5) ? 32'h0000000c : + // Undefined instruction interrupt vector + (i_interrupt_vector_sel == 3'd6) ? 32'h00000004 : + // Software (SWI) interrupt vector + (i_interrupt_vector_sel == 3'd7) ? 32'h00000008 : + // Default is the address exception interrupt + 32'h00000014 ; + + +// ======================================================== +// Address Select +// ======================================================== + +// If rd is the pc, then seperate the address bits from the status bits for +// generating the next address to fetch +assign alu_out_pc_filtered = pc_wen && i_pc_sel == 2'd1 ? pcf(alu_out) : alu_out; + +// if current instruction does not execute because it does not meet the condition +// then address advances to next instruction +assign o_address_nxt = (!execute) ? (i_fetch_abort ? pc : pc_plus4 ) : + (i_address_sel == 4'd0) ? pc_plus4 : + (i_address_sel == 4'd1) ? alu_out_pc_filtered : + (i_address_sel == 4'd2) ? interrupt_vector : + (i_address_sel == 4'd3) ? pc : + (i_address_sel == 4'd4) ? rn : + (i_address_sel == 4'd5) ? address_plus4 : // MTRANS address incrementer + (i_address_sel == 4'd6) ? alu_plus4 : // MTRANS decrement after + rn_plus4 ; // MTRANS increment before + +// Data accesses use 32-bit address space, but instruction +// accesses are restricted to 26 bit space +assign adex_nxt = |o_address_nxt[31:26] && !i_data_access_exec; + +// ======================================================== +// Program Counter Select +// ======================================================== +// If current instruction does not execute because it does not meet the condition +// then PC advances to next instruction +assign pc_nxt = (!execute) ? i_fetch_abort ? pc : pc_plus4 : + i_pc_sel == 2'd0 ? pc_plus4 : + i_pc_sel == 2'd1 ? alu_out : + interrupt_vector ; + + +// ======================================================== +// Register Write Select +// ======================================================== +wire [31:0] save_int_pc; +wire [31:0] save_int_pc_m4; + +assign save_int_pc = { status_bits_flags, + status_bits_irq_mask, + status_bits_firq_mask, + pc[25:2], + status_bits_mode }; + + +assign save_int_pc_m4 = { status_bits_flags, + status_bits_irq_mask, + status_bits_firq_mask, + pc_minus4[25:2], + status_bits_mode }; + + +assign reg_write_nxt = i_reg_write_sel == 3'd0 ? alu_out : + // save pc to lr on an interrupt + i_reg_write_sel == 3'd1 ? save_int_pc_m4 : + // to update Rd at the end of Multiplication + i_reg_write_sel == 3'd2 ? multiply_out : + i_reg_write_sel == 3'd3 ? o_status_bits : + i_reg_write_sel == 3'd5 ? i_copro_read_data : // mrc + i_reg_write_sel == 3'd6 ? base_address : + save_int_pc ; + + +// ======================================================== +// Byte Enable Select +// ======================================================== +assign byte_enable_nxt = i_byte_enable_sel == 2'd0 ? 4'b1111 : // word write + i_byte_enable_sel == 2'd2 ? // halfword write + ( o_address_nxt[1] == 1'd0 ? 4'b0011 : + 4'b1100 ) : + + o_address_nxt[1:0] == 2'd0 ? 4'b0001 : // byte write + o_address_nxt[1:0] == 2'd1 ? 4'b0010 : + o_address_nxt[1:0] == 2'd2 ? 4'b0100 : + 4'b1000 ; + + +// ======================================================== +// Write Data Select +// ======================================================== +assign write_data_nxt = i_byte_enable_sel == 2'd0 ? rd : + {4{rd[ 7:0]}} ; + + +// ======================================================== +// Conditional Execution +// ======================================================== +assign execute = conditional_execute ( i_condition, status_bits_flags ); +wire fetch_stall = i_fetch_stall & ~i_fetch_abort; +// allow the PC to increment to the next instruction when current +// instruction does not execute +assign pc_wen = i_pc_wen || !execute; + +// only update register bank if current instruction executes +assign reg_bank_wen = {{15{execute}} & i_reg_bank_wen}; + +assign reg_bank_wsel = {{4{~execute}} | i_reg_bank_wsel}; + + +// ======================================================== +// Priviledged output flag +// ======================================================== +// Need to look at status_bits_mode_nxt so switch to priviledged mode +// at the same time as assert interrupt vector address +assign priviledged_nxt = ( i_status_bits_mode_wen ? status_bits_mode_nxt : status_bits_mode ) != USR ; + + +// ======================================================== +// Write Enable +// ======================================================== +// This must be de-asserted when execute is fault +assign write_enable_nxt = execute && i_write_data_wen; + + +// ======================================================== +// Register Update +// ======================================================== + +assign translate_update = !fetch_stall && execute; +assign priviledged_update = !fetch_stall; +assign data_access_update = !fetch_stall && execute; +assign write_enable_update = !fetch_stall; +assign write_data_update = !fetch_stall && execute && i_write_data_wen; +assign exclusive_update = !fetch_stall && execute; +assign address_update = !fetch_stall; +assign byte_enable_update = !fetch_stall && execute && i_write_data_wen; +assign copro_write_data_update = !fetch_stall && execute && i_copro_write_data_wen; + +assign base_address_update = !fetch_stall && execute && i_base_address_wen; +assign status_bits_flags_update = !fetch_stall && execute && i_status_bits_flags_wen; +assign status_bits_mode_update = !fetch_stall && execute && i_status_bits_mode_wen; +assign status_bits_mode_rds_oh_update = !fetch_stall; +assign status_bits_irq_mask_update = !fetch_stall && execute && i_status_bits_irq_mask_wen; +assign status_bits_firq_mask_update = !fetch_stall && execute && i_status_bits_firq_mask_wen; + +assign status_bits_mode_rds_nr = status_bits_mode_rds_oh_update ? status_bits_mode_rds_nxt : + status_bits_mode_rds ; + +assign status_bits_mode_nr = status_bits_mode_update ? status_bits_mode_nxt : + status_bits_mode ; + +always @( posedge i_clk ) + begin + o_priviledged <= priviledged_update ? priviledged_nxt : o_priviledged; + o_exclusive <= exclusive_update ? i_exclusive_exec : o_exclusive; + o_data_access <= data_access_update ? i_data_access_exec : o_data_access; + o_write_enable <= write_enable_update ? write_enable_nxt : o_write_enable; + o_write_data <= write_data_update ? write_data_nxt : o_write_data; + o_address <= address_update ? o_address_nxt : o_address; + o_adex <= address_update ? adex_nxt : o_adex; + o_address_valid <= address_update ? 1'd1 : o_address_valid; + o_translate <= translate_update ? ~i_writeback_sel & (status_bits_mode != USR) : o_translate; + o_byte_enable <= byte_enable_update ? byte_enable_nxt : o_byte_enable; + o_copro_write_data <= copro_write_data_update ? write_data_nxt : o_copro_write_data; + + base_address <= base_address_update ? rn : base_address; + + status_bits_flags <= status_bits_flags_update ? status_bits_flags_nxt : status_bits_flags; + status_bits_mode <= status_bits_mode_nr; + status_bits_mode_rds_oh <= status_bits_mode_rds_oh_update ? status_bits_mode_rds_oh_nxt : status_bits_mode_rds_oh; + status_bits_mode_rds <= status_bits_mode_rds_nr; + status_bits_irq_mask <= status_bits_irq_mask_update ? status_bits_irq_mask_nxt : status_bits_irq_mask; + status_bits_firq_mask <= status_bits_firq_mask_update ? status_bits_firq_mask_nxt : status_bits_firq_mask; + end + + +// ======================================================== +// Instantiate Barrel Shift +// ======================================================== + +assign carry_in = i_use_carry_in ? status_bits_flags[1] : 1'd0; + +`ifndef ALTERA_FPGA +a23_barrel_shift u_barrel_shift ( +`else +a23_barrel_shift_fpga u_barrel_shift ( +`endif + .i_in ( barrel_shift_in ), + .i_carry_in ( carry_in ), + .i_shift_amount ( shift_amount ), + .i_shift_imm_zero ( i_shift_imm_zero ), + .i_function ( i_barrel_shift_function ), + + .o_out ( barrel_shift_out ), + .o_carry_out ( barrel_shift_carry ) +); + +wire barrel_shift_carry_real = i_barrel_shift_data_sel == 2'd0 ? (i_imm_shift_amount[4:1] == 0 ? status_bits_flags[1] : i_imm32[31]) : barrel_shift_carry; + +// ======================================================== +// Instantiate ALU +// ======================================================== +a23_alu u_alu ( + .i_a_in ( rn ), + .i_b_in ( barrel_shift_out ), + .i_barrel_shift_carry ( barrel_shift_carry_real ), + .i_status_bits_carry ( status_bits_flags[1] ), + .i_function ( i_alu_function ), + + .o_out ( alu_out ), + .o_flags ( alu_flags ) +); + + +// ======================================================== +// Instantiate Booth 64-bit Multiplier-Accumulator +// ======================================================== +a23_multiply u_multiply ( + .i_clk ( i_clk ), + .i_fetch_stall ( i_fetch_stall ), + .i_a_in ( rs ), + .i_b_in ( rm ), + .i_function ( i_multiply_function ), + .i_execute ( execute ), + .o_out ( multiply_out ), + .o_flags ( multiply_flags ), // [1] = N, [0] = Z + .o_done ( o_multiply_done ) +); + + +// ======================================================== +// Instantiate Register Bank +// ======================================================== +`ifndef A23_RAM_REGISTER_BANK +a23_register_bank u_register_bank( + .i_clk ( i_clk ), + .i_fetch_stall ( fetch_stall ), + .i_rm_sel ( i_rm_sel ), + .i_rds_sel ( i_rds_sel ), + .i_rn_sel ( i_rn_sel ), + .i_pc_wen ( pc_wen ), + .i_reg_bank_wen ( reg_bank_wen ), + .i_pc ( pc_nxt[25:2] ), + .i_reg ( reg_write_nxt ), + .i_mode_idec ( i_status_bits_mode ), + .i_mode_exec ( status_bits_mode ), + + .i_status_bits_flags ( status_bits_flags ), + .i_status_bits_irq_mask ( status_bits_irq_mask ), + .i_status_bits_firq_mask ( status_bits_firq_mask ), + + // pre-encoded in decode stage to speed up long path + .i_firq_not_user_mode ( i_firq_not_user_mode ), + + // use one-hot version for speed, combine with i_user_mode_regs_store + .i_mode_rds_exec ( status_bits_mode_rds_oh ), + + .i_user_mode_regs_load ( i_user_mode_regs_load ), + .o_rm ( rm ), + .o_rs ( rs ), + .o_rd ( rd ), + .o_rn ( rn ), + .o_pc ( pc ) +); +`else +a23_ram_register_bank u_register_bank( + .i_clk ( i_clk ), + .i_fetch_stall ( fetch_stall ), + .i_rm_sel ( i_rm_sel_nxt ), + .i_rds_sel ( i_rds_sel_nxt ), + .i_rn_sel ( i_rn_sel_nxt ), + .i_pc_wen ( pc_wen ), + .i_reg_bank_wsel ( reg_bank_wsel ), + .i_pc ( pc_nxt[25:2] ), + .i_reg ( reg_write_nxt ), + + .i_mode_exec_nxt ( status_bits_mode_nr ), + .i_mode_exec ( status_bits_mode ), + .i_mode_rds_exec ( status_bits_mode_rds_nr ), + .i_user_mode_regs_load ( i_user_mode_regs_load ), + + .i_status_bits_flags ( status_bits_flags ), + .i_status_bits_irq_mask ( status_bits_irq_mask ), + .i_status_bits_firq_mask ( status_bits_firq_mask ), + + .o_rm ( rm ), + .o_rs ( rs ), + .o_rd ( rd ), + .o_rn ( rn ), + .o_pc ( pc ) +); +`endif + +// ======================================================== +// Debug - non-synthesizable code +// ======================================================== +//synopsys translate_off + +wire [(2*8)-1:0] xCONDITION; +wire [(4*8)-1:0] xMODE; + +assign xCONDITION = i_condition == EQ ? "EQ" : + i_condition == NE ? "NE" : + i_condition == CS ? "CS" : + i_condition == CC ? "CC" : + i_condition == MI ? "MI" : + i_condition == PL ? "PL" : + i_condition == VS ? "VS" : + i_condition == VC ? "VC" : + i_condition == HI ? "HI" : + i_condition == LS ? "LS" : + i_condition == GE ? "GE" : + i_condition == LT ? "LT" : + i_condition == GT ? "GT" : + i_condition == LE ? "LE" : + i_condition == AL ? "AL" : + "NV " ; + +assign xMODE = status_bits_mode == SVC ? "SVC" : + status_bits_mode == IRQ ? "IRQ" : + status_bits_mode == FIRQ ? "FIRQ" : + status_bits_mode == USR ? "USR" : + "XXX" ; + + +//synopsys translate_on + +initial begin + + o_copro_write_data = 32'd0; + o_write_data = 32'd0; + o_address = 32'hdead_dead; + o_adex = 1'd0; // Address Exception + o_address_valid = 1'd0; // Prevents the reset address value being a + o_priviledged = 1'd0; // Priviledged access + o_exclusive = 1'd0; // swap access + o_write_enable = 1'd0; + o_translate = 1'd0; + o_byte_enable = 4'd0; + o_data_access = 1'd0; // To Fetch stage. high = data fetch; + +end +endmodule + + diff --git a/amber/a23_fetch.v b/amber/a23_fetch.v new file mode 100644 index 0000000..ad15f5c --- /dev/null +++ b/amber/a23_fetch.v @@ -0,0 +1,180 @@ +////////////////////////////////////////////////////////////////// +// // +// Fetch - Instantiates the fetch stage sub-modules of // +// the Amber 2 Core // +// // +// This file is part of the Amber project // +// http://www.opencores.org/project,amber // +// // +// Description // +// Instantiates the Cache and Wishbone I/F // +// Also contains a little bit of logic to decode memory // +// accesses to decide if they are cached or not // +// // +// Author(s): // +// - Conor Santifort, csantifort.amber@gmail.com // +// // +////////////////////////////////////////////////////////////////// +// // +// Copyright (C) 2010 Authors and OPENCORES.ORG // +// // +// This source file may be used and distributed without // +// restriction provided that this copyright statement is not // +// removed from the file and that any derivative work contains // +// the original copyright notice and the associated disclaimer. // +// // +// This source file is free software; you can redistribute it // +// and/or modify it under the terms of the GNU Lesser General // +// Public License as published by the Free Software Foundation; // +// either version 2.1 of the License, or (at your option) any // +// later version. // +// // +// This source 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 Lesser General Public License for more // +// details. // +// // +// You should have received a copy of the GNU Lesser General // +// Public License along with this source; if not, download it // +// from http://www.opencores.org/lgpl.shtml // +// // +////////////////////////////////////////////////////////////////// + + +module a23_fetch +( +input i_clk, + +input [31:0] i_address, +input i_address_valid, +input [31:0] i_address_nxt, // un-registered version of address to the cache rams +input [31:0] i_write_data, +input i_write_enable, +output [31:0] o_read_data, +input i_priviledged, +input i_exclusive, // high for read part of swap access +input [3:0] i_byte_enable, +input i_data_access, // high for data petch, low for instruction fetch +input i_translate, +input i_cache_enable, // cache enable +input i_cache_flush, // cache flush +input [31:0] i_cacheable_area, // each bit corresponds to 2MB address space +input i_system_rdy, +output o_fetch_abort, +output o_fetch_stall, // when this is asserted all registers + // in all 3 pipeline stages are held + // at their current values + +// Wishbone Master I/F +output [31:0] o_wb_adr, +output [3:0] o_wb_sel, +output o_wb_we, +input [31:0] i_wb_dat, +output [31:0] o_wb_dat, +output o_wb_cyc, +output o_wb_stb, +output o_wb_tga, +input i_wb_ack, +input i_wb_err + +); + +`include "memory_configuration.v" + +wire cache_stall; +wire wb_stall; +wire [31:0] cache_read_data; +wire sel_cache; +wire sel_wb; +wire cache_wb_req; +wire address_cachable; + +// ====================================== +// Memory Decode +// ====================================== +assign address_cachable = in_cachable_mem( i_address ) && i_cacheable_area[i_address[25:21]]; + +assign sel_cache = address_cachable && i_address_valid && i_cache_enable && !i_exclusive; + +// Don't start wishbone transfers when the cache is stalling the core +// The cache stalls the core during its initialization sequence +assign sel_wb = !sel_cache && i_address_valid && !(cache_stall); + +// Return read data either from the wishbone bus or the cache +assign o_read_data = sel_cache ? cache_read_data : + sel_wb ? i_wb_dat : + 32'hffeeddcc ; + +// Stall the instruction decode and execute stages of the core +// when the fetch stage needs more than 1 cycle to return the requested +// read data +assign o_fetch_stall = !i_system_rdy || wb_stall || cache_stall; +assign o_fetch_abort = wb_abort; + +// ====================================== +// L1 Cache (Unified Instruction and Data) +// ====================================== +a23_cache u_cache ( + .i_clk ( i_clk ), + + .i_select ( sel_cache ), + .i_exclusive ( i_exclusive ), + .i_write_data ( i_write_data ), + .i_write_enable ( i_write_enable ), + .i_address ( i_address ), + .i_address_nxt ( i_address_nxt ), + .i_byte_enable ( i_byte_enable ), + .i_cache_enable ( i_cache_enable ), + .i_cache_flush ( i_cache_flush ), + .o_read_data ( cache_read_data ), + + .o_stall ( cache_stall ), + .i_core_stall ( o_fetch_stall ), + .o_wb_req ( cache_wb_req ), + .i_wb_address ( o_wb_adr ), + .i_wb_read_data ( i_wb_dat ), + .i_wb_stall ( o_wb_stb & ~i_wb_ack ) +); + + +wire wb_abort; + +// ====================================== +// Wishbone Master I/F +// ====================================== +a23_wishbone u_wishbone ( + // CPU Side + .i_clk ( i_clk ), + + // Core Accesses to Wishbone bus + .i_select ( sel_wb ), + .i_write_data ( i_write_data ), + .i_write_enable ( i_write_enable ), + .i_byte_enable ( i_byte_enable ), + .i_data_access ( i_data_access ), + .i_exclusive ( i_exclusive ), + .i_translate ( i_translate ), + .i_address ( i_address ), + .o_stall ( wb_stall ), + .o_abort ( wb_abort ), + + // Cache Accesses to Wishbone bus + // L1 Cache enable - used for hprot + .i_cache_req ( cache_wb_req ), + + .o_wb_adr ( o_wb_adr ), + .o_wb_sel ( o_wb_sel ), + .o_wb_we ( o_wb_we ), + .i_wb_dat ( i_wb_dat ), + .o_wb_dat ( o_wb_dat ), + .o_wb_cyc ( o_wb_cyc ), + .o_wb_stb ( o_wb_stb ), + .i_wb_ack ( i_wb_ack ), + .i_wb_err ( i_wb_err ), + .o_wb_tga ( o_wb_tga ) +); + + +endmodule + diff --git a/amber/a23_functions.v b/amber/a23_functions.v new file mode 100644 index 0000000..b4d9081 --- /dev/null +++ b/amber/a23_functions.v @@ -0,0 +1,174 @@ +////////////////////////////////////////////////////////////////// +// // +// Functions for Amber 2 Core // +// // +// This file is part of the Amber project // +// http://www.opencores.org/project,amber // +// // +// Description // +// Functions used in more than one module // +// // +// Author(s): // +// - Conor Santifort, csantifort.amber@gmail.com // +// // +////////////////////////////////////////////////////////////////// +// // +// Copyright (C) 2010 Authors and OPENCORES.ORG // +// // +// This source file may be used and distributed without // +// restriction provided that this copyright statement is not // +// removed from the file and that any derivative work contains // +// the original copyright notice and the associated disclaimer. // +// // +// This source file is free software; you can redistribute it // +// and/or modify it under the terms of the GNU Lesser General // +// Public License as published by the Free Software Foundation; // +// either version 2.1 of the License, or (at your option) any // +// later version. // +// // +// This source 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 Lesser General Public License for more // +// details. // +// // +// You should have received a copy of the GNU Lesser General // +// Public License along with this source; if not, download it // +// from http://www.opencores.org/lgpl.shtml // +// // +////////////////////////////////////////////////////////////////// + + +// ======================================================== +// PC Filter - Remove the status bits +// ======================================================== +function [31:0] pcf; +input [31:0] pc_reg; + begin + pcf = {6'd0, pc_reg[25:2], 2'd0}; + end +endfunction + + +// ======================================================== +// 4-bit to 16-bit 1-hot decode +// ======================================================== +function [14:0] decode; +input [3:0] reg_sel; +begin +case ( reg_sel ) + 4'h0: decode = 15'h0001; + 4'h1: decode = 15'h0002; + 4'h2: decode = 15'h0004; + 4'h3: decode = 15'h0008; + 4'h4: decode = 15'h0010; + 4'h5: decode = 15'h0020; + 4'h6: decode = 15'h0040; + 4'h7: decode = 15'h0080; + 4'h8: decode = 15'h0100; + 4'h9: decode = 15'h0200; + 4'ha: decode = 15'h0400; + 4'hb: decode = 15'h0800; + 4'hc: decode = 15'h1000; + 4'hd: decode = 15'h2000; + 4'he: decode = 15'h4000; + default: decode = 15'h0000; +endcase +end +endfunction + + +// ======================================================== +// Convert Stats Bits Mode to one-hot encoded version +// ======================================================== +function [3:0] oh_status_bits_mode; +input [1:0] fn_status_bits_mode; +begin +oh_status_bits_mode = + fn_status_bits_mode == SVC ? 1'd1 << OH_SVC : + fn_status_bits_mode == IRQ ? 1'd1 << OH_IRQ : + fn_status_bits_mode == FIRQ ? 1'd1 << OH_FIRQ : + 1'd1 << OH_USR ; +end +endfunction + +// ======================================================== +// Convert mode into ascii name +// ======================================================== +function [(14*8)-1:0] mode_name; +input [4:0] mode; +begin + +mode_name = mode == USR ? "User " : + mode == SVC ? "Supervisor " : + mode == IRQ ? "Interrupt " : + mode == FIRQ ? "Fast Interrupt" : + "UNKNOWN " ; +end +endfunction + + +// ======================================================== +// Conditional Execution Function +// ======================================================== +// EQ Z set +// NE Z clear +// CS C set +// CC C clear +// MI N set +// PL N clear +// VS V set +// VC V clear +// HI C set and Z clear +// LS C clear or Z set +// GE N == V +// LT N != V +// GT Z == 0,N == V +// LE Z == 1 or N != V +// AL Always (unconditional) +// NV Never + +function conditional_execute; +input [3:0] condition; +input [3:0] flags; +begin +conditional_execute + = ( condition == AL ) || + ( condition == EQ && flags[2] ) || + ( condition == NE && !flags[2] ) || + ( condition == CS && flags[1] ) || + ( condition == CC && !flags[1] ) || + ( condition == MI && flags[3] ) || + ( condition == PL && !flags[3] ) || + ( condition == VS && flags[0] ) || + ( condition == VC && !flags[0] ) || + + ( condition == HI && flags[1] && !flags[2] ) || + ( condition == LS && (!flags[1] || flags[2]) ) || + + ( condition == GE && flags[3] == flags[0] ) || + ( condition == LT && flags[3] != flags[0] ) || + + ( condition == GT && !flags[2] && flags[3] == flags[0] ) || + ( condition == LE && (flags[2] || flags[3] != flags[0])) ; + +end +endfunction + + +// ======================================================== +// Log 2 +// ======================================================== + +function [31:0] log2; +input [31:0] num; +integer i; +integer out; +begin + out = 32'd0; + for (i=0; i<30; i=i+1) + if ((2**i > num) && (out == 0)) + out = i-1; + log2 = out; +end +endfunction diff --git a/amber/a23_localparams.v b/amber/a23_localparams.v new file mode 100644 index 0000000..33c8845 --- /dev/null +++ b/amber/a23_localparams.v @@ -0,0 +1,117 @@ +////////////////////////////////////////////////////////////////// +// // +// Parameters file for Amber 2 Core // +// // +// This file is part of the Amber project // +// http://www.opencores.org/project,amber // +// // +// Description // +// Holds general parameters that are used is several core // +// modules // +// // +// Author(s): // +// - Conor Santifort, csantifort.amber@gmail.com // +// // +////////////////////////////////////////////////////////////////// +// // +// Copyright (C) 2010 Authors and OPENCORES.ORG // +// // +// This source file may be used and distributed without // +// restriction provided that this copyright statement is not // +// removed from the file and that any derivative work contains // +// the original copyright notice and the associated disclaimer. // +// // +// This source file is free software; you can redistribute it // +// and/or modify it under the terms of the GNU Lesser General // +// Public License as published by the Free Software Foundation; // +// either version 2.1 of the License, or (at your option) any // +// later version. // +// // +// This source 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 Lesser General Public License for more // +// details. // +// // +// You should have received a copy of the GNU Lesser General // +// Public License along with this source; if not, download it // +// from http://www.opencores.org/lgpl.shtml // +// // +////////////////////////////////////////////////////////////////// + + +// Instruction Types +localparam [3:0] REGOP = 4'h0, // Data processing + MULT = 4'h1, // Multiply + SWAP = 4'h2, // Single Data Swap + TRANS = 4'h3, // Single data transfer + MTRANS = 4'h4, // Multi-word data transfer + BRANCH = 4'h5, // Branch + CODTRANS = 4'h6, // Co-processor data transfer + COREGOP = 4'h7, // Co-processor data operation + CORTRANS = 4'h8, // Co-processor register transfer + SWI = 4'h9; // software interrupt + + +// Opcodes +localparam [3:0] AND = 4'h0, // Logical AND + EOR = 4'h1, // Logical Exclusive OR + SUB = 4'h2, // Subtract + RSB = 4'h3, // Reverse Subtract + ADD = 4'h4, // Add + ADC = 4'h5, // Add with Carry + SBC = 4'h6, // Subtract with Carry + RSC = 4'h7, // Reverse Subtract with Carry + TST = 4'h8, // Test (using AND operator) + TEQ = 4'h9, // Test Equivalence (using EOR operator) + CMP = 4'ha, // Compare (using Subtract operator) + CMN = 4'hb, // Compare Negated + ORR = 4'hc, // Logical OR + MOV = 4'hd, // Move + BIC = 4'he, // Bit Clear (using AND & NOT operators) + MVN = 4'hf; // Move NOT + +// Condition Encoding +localparam [3:0] EQ = 4'h0, // Equal / Z set + NE = 4'h1, // Not equal / Z clear + CS = 4'h2, // Carry set / C set + CC = 4'h3, // Carry clear / C clear + MI = 4'h4, // Minus / N set + PL = 4'h5, // Plus / N clear + VS = 4'h6, // Overflow / V set + VC = 4'h7, // No overflow / V clear + HI = 4'h8, // Unsigned higher / C set and Z clear + LS = 4'h9, // Unsigned lower + // or same / C clear or Z set + GE = 4'ha, // Signed greater + // than or equal / N == V + LT = 4'hb, // Signed less than / N != V + GT = 4'hc, // Signed greater + // than / Z == 0, N == V + LE = 4'hd, // Signed less than + // or equal / Z == 1, N != V + AL = 4'he, // Always + NV = 4'hf; // Never + +// Any instruction with a condition field of 0b1111 is UNPREDICTABLE. + +// Shift Types +localparam [1:0] LSL = 2'h0, + LSR = 2'h1, + ASR = 2'h2, + RRX = 2'h3, + ROR = 2'h3; + +// Modes +localparam [1:0] SVC = 2'b11, // Supervisor + IRQ = 2'b10, // Interrupt + FIRQ = 2'b01, // Fast Interrupt + USR = 2'b00; // User + +// One-Hot Mode encodings +localparam [5:0] OH_USR = 0, + OH_IRQ = 1, + OH_FIRQ = 2, + OH_SVC = 3; + + diff --git a/amber/a23_multiply.v b/amber/a23_multiply.v new file mode 100644 index 0000000..c220597 --- /dev/null +++ b/amber/a23_multiply.v @@ -0,0 +1,206 @@ +////////////////////////////////////////////////////////////////// +// // +// Multiplication Module for Amber 2 Core // +// // +// This file is part of the Amber project // +// http://www.opencores.org/project,amber // +// // +// Description // +// 64-bit Booth signed or unsigned multiply and // +// multiply-accumulate supported. It takes about 38 clock // +// cycles to complete an operation. // +// // +// Author(s): // +// - Conor Santifort, csantifort.amber@gmail.com // +// // +////////////////////////////////////////////////////////////////// +// // +// Copyright (C) 2010 Authors and OPENCORES.ORG // +// // +// This source file may be used and distributed without // +// restriction provided that this copyright statement is not // +// removed from the file and that any derivative work contains // +// the original copyright notice and the associated disclaimer. // +// // +// This source file is free software; you can redistribute it // +// and/or modify it under the terms of the GNU Lesser General // +// Public License as published by the Free Software Foundation; // +// either version 2.1 of the License, or (at your option) any // +// later version. // +// // +// This source 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 Lesser General Public License for more // +// details. // +// // +// You should have received a copy of the GNU Lesser General // +// Public License along with this source; if not, download it // +// from http://www.opencores.org/lgpl.shtml // +// // +////////////////////////////////////////////////////////////////// + + + +// bit 0 go, bit 1 accumulate +// Command: +// 4'b01 : MUL - 32 bit multiplication +// 4'b11 : MLA - 32 bit multiply and accumulate +// +// 34-bit Booth adder +// The adder needs to be 34 bit to deal with signed and unsigned 32-bit +// multiplication inputs. This adds 1 extra bit. Then to deal with the +// case of two max negative numbers another bit is required. +// + +module a23_multiply ( +input i_clk, +input i_fetch_stall, + +input [31:0] i_a_in, // Rds +input [31:0] i_b_in, // Rm +input [1:0] i_function, +input i_execute, + +output [31:0] o_out, +output [1:0] o_flags, // [1] = N, [0] = Z +output reg o_done +); + + +wire enable; +wire accumulate; +wire [33:0] multiplier; +wire [33:0] multiplier_bar; +wire [33:0] sum; +wire [33:0] sum34_b; + +reg [5:0] count = 'd0; +reg [5:0] count_nxt; +reg [67:0] product = 'd0; +reg [67:0] product_nxt; +reg [1:0] flags_nxt; +wire [32:0] sum_acc1; // the MSB is the carry out for the upper 32 bit addition + + +assign enable = i_function[0]; +assign accumulate = i_function[1]; + +assign multiplier = { 2'd0, i_a_in} ; +assign multiplier_bar = ~{ 2'd0, i_a_in} + 34'd1 ; + +assign sum34_b = product[1:0] == 2'b01 ? multiplier : + product[1:0] == 2'b10 ? multiplier_bar : + 34'd0 ; + + +// Use DSP modules from Xilinx Spartan6 FPGA devices +`ifdef XILINX_FPGA + // ----------------------------------- + // 34-bit adder - booth multiplication + // ----------------------------------- + `ifdef XILINX_SPARTAN6_FPGA + xs6_addsub_n #(.WIDTH(34)) + `endif + `ifdef XILINX_VIRTEX6_FPGA + xv6_addsub_n #(.WIDTH(34)) + `endif + + u_xx_addsub_34_sum ( + .i_a ( product[67:34] ), + .i_b ( sum34_b ), + .i_cin ( 1'd0 ), + .i_sub ( 1'd0 ), + .o_sum ( sum ), + .o_co ( ) + ); + + // ------------------------------------ + // 33-bit adder - accumulate operations + // ------------------------------------ + `ifdef XILINX_SPARTAN6_FPGA + xs6_addsub_n #(.WIDTH(33)) + `endif + `ifdef XILINX_VIRTEX6_FPGA + xv6_addsub_n #(.WIDTH(33)) + `endif + u_xx_addsub_33_acc1 ( + .i_a ( {1'd0, product[32:1]} ), + .i_b ( {1'd0, i_a_in} ), + .i_cin ( 1'd0 ), + .i_sub ( 1'd0 ), + .o_sum ( sum_acc1 ), + .o_co ( ) + ); + +`else + + // ----------------------------------- + // 34-bit adder - booth multiplication + // ----------------------------------- + assign sum = product[67:34] + sum34_b; + + // ------------------------------------ + // 33-bit adder - accumulate operations + // ------------------------------------ + assign sum_acc1 = {1'd0, product[32:1]} + {1'd0, i_a_in}; + +`endif + + +always @* + begin + // Defaults + count_nxt = count; + product_nxt = product; + + // update Negative and Zero flags + // Use registered value of product so this adds an extra cycle + // but this avoids having the 64-bit zero comparator on the + // main adder path + flags_nxt = { product[32], product[32:1] == 32'd0 }; + + + if ( count == 6'd0 ) + product_nxt = {33'd0, 1'd0, i_b_in, 1'd0 } ; + else if ( count <= 6'd33 ) + product_nxt = { sum[33], sum, product[33:1]} ; + else if ( count == 6'd34 && accumulate ) + begin + // Note that bit 0 is not part of the product. It is used during the booth + // multiplication algorithm + product_nxt = { product[64:33], sum_acc1[31:0], 1'd0}; // Accumulate + end + + // Multiplication state counter + if (count == 6'd0) // start + count_nxt = enable ? 6'd1 : 6'd0; + else if ((count == 6'd34 && !accumulate) || // MUL + (count == 6'd35 && accumulate) ) // MLA + count_nxt = 6'd0; + else + count_nxt = count + 1'd1; + end + + +always @ ( posedge i_clk ) + if ( !i_fetch_stall ) + begin + count <= i_execute ? count_nxt : count; + product <= i_execute ? product_nxt : product; + o_done <= i_execute ? count == 6'd31 : o_done; + end + +// Outputs +assign o_out = product[32:1]; +assign o_flags = flags_nxt; + +initial begin + + o_done = 1'd0; // goes high 2 cycles before completion + +end + +endmodule + + diff --git a/amber/a23_ram_register_bank.v b/amber/a23_ram_register_bank.v new file mode 100644 index 0000000..ed00dec --- /dev/null +++ b/amber/a23_ram_register_bank.v @@ -0,0 +1,324 @@ +////////////////////////////////////////////////////////////////// +// // +// RAM-based register Bank for Amber Core // +// // +// This file is part of the Amber project // +// http://www.opencores.org/project,amber // +// // +// Description // +// Contains 37 32-bit registers, 16 of which are visible // +// ina any one operating mode. // +// The block is designed using syncronous RAM primitive, // +// and fits well into an FPGA design // +// // +// Author(s): // +// - Dmitry Tarnyagin, dmitry.tarnyagin@lockless.no // +// // +////////////////////////////////////////////////////////////////// +// // +// Copyright (C) 2010 Authors and OPENCORES.ORG // +// // +// This source file may be used and distributed without // +// restriction provided that this copyright statement is not // +// removed from the file and that any derivative work contains // +// the original copyright notice and the associated disclaimer. // +// // +// This source file is free software; you can redistribute it // +// and/or modify it under the terms of the GNU Lesser General // +// Public License as published by the Free Software Foundation; // +// either version 2.1 of the License, or (at your option) any // +// later version. // +// // +// This source 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 Lesser General Public License for more // +// details. // +// // +// You should have received a copy of the GNU Lesser General // +// Public License along with this source; if not, download it // +// from http://www.opencores.org/lgpl.shtml // +// // +////////////////////////////////////////////////////////////////// + +module a23_ram_register_bank ( + +input i_clk, +input i_fetch_stall, + +input [1:0] i_mode_exec, // registered cpu mode from execution stage +input [1:0] i_mode_exec_nxt, // 1 periods delayed from i_mode_idec + // Used for register reads +input [1:0] i_mode_rds_exec, // Use raw version in this implementation, + // includes i_user_mode_regs_store +input i_user_mode_regs_load, +input [3:0] i_rm_sel, +input [3:0] i_rds_sel, +input [3:0] i_rn_sel, + +input i_pc_wen, +input [3:0] i_reg_bank_wsel, + +input [23:0] i_pc, // program counter [25:2] +input [31:0] i_reg, + +input [3:0] i_status_bits_flags, +input i_status_bits_irq_mask, +input i_status_bits_firq_mask, + +output [31:0] o_rm, +output [31:0] o_rs, +output [31:0] o_rd, +output [31:0] o_rn, +output [31:0] o_pc + +); + +`include "a23_localparams.v" +`include "a23_functions.v" + +wire [1:0] mode_idec; +wire [1:0] mode_exec; +wire [1:0] mode_rds; + +wire [4:0] rm_addr; +wire [4:0] rds_addr; +wire [4:0] rn_addr; +wire [4:0] wr_addr; + +// Register pool in embedded ram memory +reg [31:0] reg_ram_n[31:0]; +reg [31:0] reg_ram_m[31:0]; +reg [31:0] reg_ram_ds[31:0]; + +wire [31:0] rds_out; +wire [31:0] rm_out; +wire [31:0] rn_out; + +// Synchronous ram input buffering +reg [4:0] rm_addr_reg; +reg [4:0] rds_addr_reg; +reg [4:0] rn_addr_reg; + +// User Mode Registers +reg [23:0] r15 = 24'hc0_ffee; + +wire [31:0] r15_out_rm; +wire [31:0] r15_out_rm_nxt; +wire [31:0] r15_out_rn; + +// r15 selectors +reg rn_15 = 1'b0; +reg rm_15 = 1'b0; +reg rds_15 = 1'b0; + +// Write Enables from execute stage +assign mode_idec = i_mode_exec_nxt & ~{2{i_user_mode_regs_load}}; +assign wr_addr = reg_addr(mode_idec, i_reg_bank_wsel); + +// Read Enables from stage 1 (fetch) +assign mode_exec = i_mode_exec_nxt; +assign rm_addr = reg_addr(mode_exec, i_rm_sel); +assign rn_addr = reg_addr(mode_exec, i_rn_sel); + +// Rds +assign mode_rds = i_mode_rds_exec; +assign rds_addr = reg_addr(mode_rds, i_rds_sel); + + +// ======================================================== +// r15 Register Read based on Mode +// ======================================================== +assign r15_out_rm = { i_status_bits_flags, + i_status_bits_irq_mask, + i_status_bits_firq_mask, + r15, + i_mode_exec}; + +assign r15_out_rm_nxt = { i_status_bits_flags, + i_status_bits_irq_mask, + i_status_bits_firq_mask, + i_pc, + i_mode_exec}; + +assign r15_out_rn = {6'd0, r15, 2'd0}; + + +// ======================================================== +// Program Counter out +// ======================================================== +assign o_pc = r15_out_rn; + +// ======================================================== +// Rm Selector +// ======================================================== +assign rm_out = reg_ram_m[rm_addr_reg]; + +assign o_rm = rm_15 ? r15_out_rm : + rm_out; + +// ======================================================== +// Rds Selector +// ======================================================== +assign rds_out = reg_ram_ds[rds_addr_reg]; + +assign o_rs = rds_15 ? r15_out_rn : + rds_out; + +// ======================================================== +// Rd Selector +// ======================================================== +assign o_rd = rds_15 ? r15_out_rm_nxt : + rds_out; + +// ======================================================== +// Rn Selector +// ======================================================== +assign rn_out = reg_ram_n[rn_addr_reg]; + +assign o_rn = rn_15 ? r15_out_rn : + rn_out; +// ======================================================== +// Register Update +// ======================================================== +always @ ( posedge i_clk ) + if (!i_fetch_stall) + begin + + // Register write. + // Actually the code is synthesed as a syncronous ram + // with an additional pass-through multiplexor for + // read-when-write handling. + reg_ram_n[wr_addr] <= i_reg; + reg_ram_m[wr_addr] <= i_reg; + reg_ram_ds[wr_addr] <= i_reg; + r15 <= i_pc_wen ? i_pc : r15; + + // The latching is actually implemented in a hard block. + rn_addr_reg <= rn_addr; + rm_addr_reg <= rm_addr; + rds_addr_reg <= rds_addr; + + rn_15 <= i_rn_sel == 4'hF; + rm_15 <= i_rm_sel == 4'hF; + rds_15 <= i_rds_sel == 4'hF; + end + +// ======================================================== +// Register mapping: +// ======================================================== +// 0xxxx : r0 - r14 +// 10xxx : r8_firq - r14_firq +// 110xx : r13_irq - r14_irq +// 111xx : r13_svc - r14_svc + +function [4:0] reg_addr; +input [1:0] mode; +input [3:0] sel; +begin + casez ({mode, sel}) // synthesis full_case parallel_case + 6'b??0???: reg_addr = {1'b0, sel}; // r0 - r7 + 6'b1?1100: reg_addr = {1'b0, sel}; // irq and svc r12 + 6'b001???: reg_addr = {1'b0, sel}; // user r8 - r14 + 6'b011???: reg_addr = {2'b10, sel[2:0]}; // fiq r8-r14 + 6'b1?10??: reg_addr = {1'b0, sel}; // irq and svc r8-r11 + 6'b101101: reg_addr = {3'b110, sel[1:0]}; // irq r13 + 6'b101110: reg_addr = {3'b110, sel[1:0]}; // irq r14 + 6'b101111: reg_addr = {3'b110, sel[1:0]}; // irq r15, just to make the case full + 6'b111101: reg_addr = {3'b111, sel[1:0]}; // svc r13 + 6'b111110: reg_addr = {3'b111, sel[1:0]}; // svc r14 + 6'b111111: reg_addr = {3'b111, sel[1:0]}; // svc r15, just to make the case full + endcase +end +endfunction + +// synthesis translate_off +// To be used as probes... +wire [31:0] r0; +wire [31:0] r1; +wire [31:0] r2; +wire [31:0] r3; +wire [31:0] r4; +wire [31:0] r5; +wire [31:0] r6; +wire [31:0] r7; +wire [31:0] r8; +wire [31:0] r9; +wire [31:0] r10; +wire [31:0] r11; +wire [31:0] r12; +wire [31:0] r13; +wire [31:0] r14; +wire [31:0] r13_svc; +wire [31:0] r14_svc; +wire [31:0] r13_irq; +wire [31:0] r14_irq; +wire [31:0] r8_firq; +wire [31:0] r9_firq; +wire [31:0] r10_firq; +wire [31:0] r11_firq; +wire [31:0] r12_firq; +wire [31:0] r13_firq; +wire [31:0] r14_firq; +wire [31:0] r0_out; +wire [31:0] r1_out; +wire [31:0] r2_out; +wire [31:0] r3_out; +wire [31:0] r4_out; +wire [31:0] r5_out; +wire [31:0] r6_out; +wire [31:0] r7_out; +wire [31:0] r8_out; +wire [31:0] r9_out; +wire [31:0] r10_out; +wire [31:0] r11_out; +wire [31:0] r12_out; +wire [31:0] r13_out; +wire [31:0] r14_out; + +assign r0 = reg_ram_m[ 0]; +assign r1 = reg_ram_m[ 1]; +assign r2 = reg_ram_m[ 2]; +assign r3 = reg_ram_m[ 3]; +assign r4 = reg_ram_m[ 4]; +assign r5 = reg_ram_m[ 5]; +assign r6 = reg_ram_m[ 6]; +assign r7 = reg_ram_m[ 7]; +assign r8 = reg_ram_m[ 8]; +assign r9 = reg_ram_m[ 9]; +assign r10 = reg_ram_m[10]; +assign r11 = reg_ram_m[11]; +assign r12 = reg_ram_m[12]; +assign r13 = reg_ram_m[13]; +assign r14 = reg_ram_m[14]; +assign r13_svc = reg_ram_m[29]; +assign r14_svc = reg_ram_m[30]; +assign r13_irq = reg_ram_m[25]; +assign r14_irq = reg_ram_m[26]; +assign r8_firq = reg_ram_m[16]; +assign r9_firq = reg_ram_m[17]; +assign r10_firq = reg_ram_m[18]; +assign r11_firq = reg_ram_m[19]; +assign r12_firq = reg_ram_m[20]; +assign r13_firq = reg_ram_m[21]; +assign r14_firq = reg_ram_m[22]; +assign r0_out = reg_ram_m[reg_addr(mode_exec, 0)]; +assign r1_out = reg_ram_m[reg_addr(mode_exec, 1)]; +assign r2_out = reg_ram_m[reg_addr(mode_exec, 2)]; +assign r3_out = reg_ram_m[reg_addr(mode_exec, 3)]; +assign r4_out = reg_ram_m[reg_addr(mode_exec, 4)]; +assign r5_out = reg_ram_m[reg_addr(mode_exec, 5)]; +assign r6_out = reg_ram_m[reg_addr(mode_exec, 6)]; +assign r7_out = reg_ram_m[reg_addr(mode_exec, 7)]; +assign r8_out = reg_ram_m[reg_addr(mode_exec, 8)]; +assign r9_out = reg_ram_m[reg_addr(mode_exec, 9)]; +assign r10_out = reg_ram_m[reg_addr(mode_exec, 10)]; +assign r11_out = reg_ram_m[reg_addr(mode_exec, 11)]; +assign r12_out = reg_ram_m[reg_addr(mode_exec, 12)]; +assign r13_out = reg_ram_m[reg_addr(mode_exec, 13)]; +assign r14_out = reg_ram_m[reg_addr(mode_exec, 14)]; +// synthesis translate_on + +endmodule + + diff --git a/amber/a23_register_bank.v b/amber/a23_register_bank.v new file mode 100644 index 0000000..bf70724 --- /dev/null +++ b/amber/a23_register_bank.v @@ -0,0 +1,374 @@ +////////////////////////////////////////////////////////////////// +// // +// Register Bank for Amber Core // +// // +// This file is part of the Amber project // +// http://www.opencores.org/project,amber // +// // +// Description // +// Contains 37 32-bit registers, 16 of which are visible // +// ina any one operating mode. Registers use real flipflops, // +// rather than SRAM. This makes sense for an FPGA // +// implementation, where flipflops are plentiful. // +// // +// Author(s): // +// - Conor Santifort, csantifort.amber@gmail.com // +// // +////////////////////////////////////////////////////////////////// +// // +// Copyright (C) 2010 Authors and OPENCORES.ORG // +// // +// This source file may be used and distributed without // +// restriction provided that this copyright statement is not // +// removed from the file and that any derivative work contains // +// the original copyright notice and the associated disclaimer. // +// // +// This source file is free software; you can redistribute it // +// and/or modify it under the terms of the GNU Lesser General // +// Public License as published by the Free Software Foundation; // +// either version 2.1 of the License, or (at your option) any // +// later version. // +// // +// This source 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 Lesser General Public License for more // +// details. // +// // +// You should have received a copy of the GNU Lesser General // +// Public License along with this source; if not, download it // +// from http://www.opencores.org/lgpl.shtml // +// // +////////////////////////////////////////////////////////////////// + +module a23_register_bank ( + +input i_clk, +input i_fetch_stall, + +input [1:0] i_mode_idec, // user, supervisor, irq_idec, firq_idec etc. + // Used for register writes +input [1:0] i_mode_exec, // 1 periods delayed from i_mode_idec + // Used for register reads +input [3:0] i_mode_rds_exec, // Use one-hot version specifically for rds, + // includes i_user_mode_regs_store +input i_user_mode_regs_load, +input i_firq_not_user_mode, +input [3:0] i_rm_sel, +input [3:0] i_rds_sel, +input [3:0] i_rn_sel, + +input i_pc_wen, +input [14:0] i_reg_bank_wen, + +input [23:0] i_pc, // program counter [25:2] +input [31:0] i_reg, + +input [3:0] i_status_bits_flags, +input i_status_bits_irq_mask, +input i_status_bits_firq_mask, + +output [31:0] o_rm, +output reg [31:0] o_rs, +output reg [31:0] o_rd, +output [31:0] o_rn, +output [31:0] o_pc + +); + +`include "a23_localparams.v" +`include "a23_functions.v" + + +// User Mode Registers +reg [31:0] r0 = 32'hdead_beef; +reg [31:0] r1 = 32'hdead_beef; +reg [31:0] r2 = 32'hdead_beef; +reg [31:0] r3 = 32'hdead_beef; +reg [31:0] r4 = 32'hdead_beef; +reg [31:0] r5 = 32'hdead_beef; +reg [31:0] r6 = 32'hdead_beef; +reg [31:0] r7 = 32'hdead_beef; +reg [31:0] r8 = 32'hdead_beef; +reg [31:0] r9 = 32'hdead_beef; +reg [31:0] r10 = 32'hdead_beef; +reg [31:0] r11 = 32'hdead_beef; +reg [31:0] r12 = 32'hdead_beef; +reg [31:0] r13 = 32'hdead_beef; +reg [31:0] r14 = 32'hdead_beef; +reg [23:0] r15 = 24'hc0_ffee; + +wire [31:0] r0_out; +wire [31:0] r1_out; +wire [31:0] r2_out; +wire [31:0] r3_out; +wire [31:0] r4_out; +wire [31:0] r5_out; +wire [31:0] r6_out; +wire [31:0] r7_out; +wire [31:0] r8_out; +wire [31:0] r9_out; +wire [31:0] r10_out; +wire [31:0] r11_out; +wire [31:0] r12_out; +wire [31:0] r13_out; +wire [31:0] r14_out; +wire [31:0] r15_out_rm; +wire [31:0] r15_out_rm_nxt; +wire [31:0] r15_out_rn; + +wire [31:0] r8_rds; +wire [31:0] r9_rds; +wire [31:0] r10_rds; +wire [31:0] r11_rds; +wire [31:0] r12_rds; +wire [31:0] r13_rds; +wire [31:0] r14_rds; + +// Supervisor Mode Registers +reg [31:0] r13_svc = 32'hdead_beef; +reg [31:0] r14_svc = 32'hdead_beef; + +// Interrupt Mode Registers +reg [31:0] r13_irq = 32'hdead_beef; +reg [31:0] r14_irq = 32'hdead_beef; + +// Fast Interrupt Mode Registers +reg [31:0] r8_firq = 32'hdead_beef; +reg [31:0] r9_firq = 32'hdead_beef; +reg [31:0] r10_firq = 32'hdead_beef; +reg [31:0] r11_firq = 32'hdead_beef; +reg [31:0] r12_firq = 32'hdead_beef; +reg [31:0] r13_firq = 32'hdead_beef; +reg [31:0] r14_firq = 32'hdead_beef; + +wire usr_exec; +wire svc_exec; +wire irq_exec; +wire firq_exec; + +wire usr_idec; +wire svc_idec; +wire irq_idec; +wire firq_idec; + + // Write Enables from execute stage +assign usr_idec = i_user_mode_regs_load || i_mode_idec == USR; +assign svc_idec = !i_user_mode_regs_load && i_mode_idec == SVC; +assign irq_idec = !i_user_mode_regs_load && i_mode_idec == IRQ; + +// pre-encoded in decode stage to speed up long path +assign firq_idec = i_firq_not_user_mode; + + // Read Enables from stage 1 (fetch) +assign usr_exec = i_mode_exec == USR; +assign svc_exec = i_mode_exec == SVC; +assign irq_exec = i_mode_exec == IRQ; +assign firq_exec = i_mode_exec == FIRQ; + + +// ======================================================== +// Register Update +// ======================================================== +always @ ( posedge i_clk ) + if (!i_fetch_stall) + begin + r0 <= i_reg_bank_wen[0 ] ? i_reg : r0; + r1 <= i_reg_bank_wen[1 ] ? i_reg : r1; + r2 <= i_reg_bank_wen[2 ] ? i_reg : r2; + r3 <= i_reg_bank_wen[3 ] ? i_reg : r3; + r4 <= i_reg_bank_wen[4 ] ? i_reg : r4; + r5 <= i_reg_bank_wen[5 ] ? i_reg : r5; + r6 <= i_reg_bank_wen[6 ] ? i_reg : r6; + r7 <= i_reg_bank_wen[7 ] ? i_reg : r7; + + r8 <= (i_reg_bank_wen[8 ] && !firq_idec) ? i_reg : r8; + r9 <= (i_reg_bank_wen[9 ] && !firq_idec) ? i_reg : r9; + r10 <= (i_reg_bank_wen[10] && !firq_idec) ? i_reg : r10; + r11 <= (i_reg_bank_wen[11] && !firq_idec) ? i_reg : r11; + r12 <= (i_reg_bank_wen[12] && !firq_idec) ? i_reg : r12; + + r8_firq <= (i_reg_bank_wen[8 ] && firq_idec) ? i_reg : r8_firq; + r9_firq <= (i_reg_bank_wen[9 ] && firq_idec) ? i_reg : r9_firq; + r10_firq <= (i_reg_bank_wen[10] && firq_idec) ? i_reg : r10_firq; + r11_firq <= (i_reg_bank_wen[11] && firq_idec) ? i_reg : r11_firq; + r12_firq <= (i_reg_bank_wen[12] && firq_idec) ? i_reg : r12_firq; + + r13 <= (i_reg_bank_wen[13] && usr_idec) ? i_reg : r13; + r14 <= (i_reg_bank_wen[14] && usr_idec) ? i_reg : r14; + + r13_svc <= (i_reg_bank_wen[13] && svc_idec) ? i_reg : r13_svc; + r14_svc <= (i_reg_bank_wen[14] && svc_idec) ? i_reg : r14_svc; + + r13_irq <= (i_reg_bank_wen[13] && irq_idec) ? i_reg : r13_irq; + r14_irq <= (i_reg_bank_wen[14] && irq_idec) ? i_reg : r14_irq; + + r13_firq <= (i_reg_bank_wen[13] && firq_idec) ? i_reg : r13_firq; + r14_firq <= (i_reg_bank_wen[14] && firq_idec) ? i_reg : r14_firq; + + r15 <= i_pc_wen ? i_pc : r15; + end + + +// ======================================================== +// Register Read based on Mode +// ======================================================== +assign r0_out = r0; +assign r1_out = r1; +assign r2_out = r2; +assign r3_out = r3; +assign r4_out = r4; +assign r5_out = r5; +assign r6_out = r6; +assign r7_out = r7; + +assign r8_out = firq_exec ? r8_firq : r8; +assign r9_out = firq_exec ? r9_firq : r9; +assign r10_out = firq_exec ? r10_firq : r10; +assign r11_out = firq_exec ? r11_firq : r11; +assign r12_out = firq_exec ? r12_firq : r12; + +assign r13_out = usr_exec ? r13 : + svc_exec ? r13_svc : + irq_exec ? r13_irq : + r13_firq ; + +assign r14_out = usr_exec ? r14 : + svc_exec ? r14_svc : + irq_exec ? r14_irq : + r14_firq ; + + +assign r15_out_rm = { i_status_bits_flags, + i_status_bits_irq_mask, + i_status_bits_firq_mask, + r15, + i_mode_exec}; + +assign r15_out_rm_nxt = { i_status_bits_flags, + i_status_bits_irq_mask, + i_status_bits_firq_mask, + i_pc, + i_mode_exec}; + +assign r15_out_rn = {6'd0, r15, 2'd0}; + + +// rds outputs +assign r8_rds = i_mode_rds_exec[OH_FIRQ] ? r8_firq : r8; +assign r9_rds = i_mode_rds_exec[OH_FIRQ] ? r9_firq : r9; +assign r10_rds = i_mode_rds_exec[OH_FIRQ] ? r10_firq : r10; +assign r11_rds = i_mode_rds_exec[OH_FIRQ] ? r11_firq : r11; +assign r12_rds = i_mode_rds_exec[OH_FIRQ] ? r12_firq : r12; + +assign r13_rds = i_mode_rds_exec[OH_USR] ? r13 : + i_mode_rds_exec[OH_SVC] ? r13_svc : + i_mode_rds_exec[OH_IRQ] ? r13_irq : + r13_firq ; + +assign r14_rds = i_mode_rds_exec[OH_USR] ? r14 : + i_mode_rds_exec[OH_SVC] ? r14_svc : + i_mode_rds_exec[OH_IRQ] ? r14_irq : + r14_firq ; + +// ======================================================== +// Program Counter out +// ======================================================== +assign o_pc = r15_out_rn; + +// ======================================================== +// Rm Selector +// ======================================================== +assign o_rm = i_rm_sel == 4'd0 ? r0_out : + i_rm_sel == 4'd1 ? r1_out : + i_rm_sel == 4'd2 ? r2_out : + i_rm_sel == 4'd3 ? r3_out : + i_rm_sel == 4'd4 ? r4_out : + i_rm_sel == 4'd5 ? r5_out : + i_rm_sel == 4'd6 ? r6_out : + i_rm_sel == 4'd7 ? r7_out : + i_rm_sel == 4'd8 ? r8_out : + i_rm_sel == 4'd9 ? r9_out : + i_rm_sel == 4'd10 ? r10_out : + i_rm_sel == 4'd11 ? r11_out : + i_rm_sel == 4'd12 ? r12_out : + i_rm_sel == 4'd13 ? r13_out : + i_rm_sel == 4'd14 ? r14_out : + r15_out_rm ; + + + + +// ======================================================== +// Rds Selector +// ======================================================== +always @* + case (i_rds_sel) + 4'd0 : o_rs = r0_out ; + 4'd1 : o_rs = r1_out ; + 4'd2 : o_rs = r2_out ; + 4'd3 : o_rs = r3_out ; + 4'd4 : o_rs = r4_out ; + 4'd5 : o_rs = r5_out ; + 4'd6 : o_rs = r6_out ; + 4'd7 : o_rs = r7_out ; + 4'd8 : o_rs = r8_rds ; + 4'd9 : o_rs = r9_rds ; + 4'd10 : o_rs = r10_rds ; + 4'd11 : o_rs = r11_rds ; + 4'd12 : o_rs = r12_rds ; + 4'd13 : o_rs = r13_rds ; + 4'd14 : o_rs = r14_rds ; + default: o_rs = r15_out_rn ; + endcase + + + +// ======================================================== +// Rd Selector +// ======================================================== +always @* + case (i_rds_sel) + 4'd0 : o_rd = r0_out ; + 4'd1 : o_rd = r1_out ; + 4'd2 : o_rd = r2_out ; + 4'd3 : o_rd = r3_out ; + 4'd4 : o_rd = r4_out ; + 4'd5 : o_rd = r5_out ; + 4'd6 : o_rd = r6_out ; + 4'd7 : o_rd = r7_out ; + 4'd8 : o_rd = r8_rds ; + 4'd9 : o_rd = r9_rds ; + 4'd10 : o_rd = r10_rds ; + 4'd11 : o_rd = r11_rds ; + 4'd12 : o_rd = r12_rds ; + 4'd13 : o_rd = r13_rds ; + 4'd14 : o_rd = r14_rds ; + default: o_rd = r15_out_rm_nxt ; + endcase + + +// ======================================================== +// Rn Selector +// ======================================================== +assign o_rn = i_rn_sel == 4'd0 ? r0_out : + i_rn_sel == 4'd1 ? r1_out : + i_rn_sel == 4'd2 ? r2_out : + i_rn_sel == 4'd3 ? r3_out : + i_rn_sel == 4'd4 ? r4_out : + i_rn_sel == 4'd5 ? r5_out : + i_rn_sel == 4'd6 ? r6_out : + i_rn_sel == 4'd7 ? r7_out : + i_rn_sel == 4'd8 ? r8_out : + i_rn_sel == 4'd9 ? r9_out : + i_rn_sel == 4'd10 ? r10_out : + i_rn_sel == 4'd11 ? r11_out : + i_rn_sel == 4'd12 ? r12_out : + i_rn_sel == 4'd13 ? r13_out : + i_rn_sel == 4'd14 ? r14_out : + r15_out_rn ; + + +endmodule + + diff --git a/amber/a23_wishbone.v b/amber/a23_wishbone.v new file mode 100644 index 0000000..8467bb1 --- /dev/null +++ b/amber/a23_wishbone.v @@ -0,0 +1,321 @@ +////////////////////////////////////////////////////////////////// +// // +// Wishbone master interface for the Amber core // +// // +// This file is part of the Amber project // +// http://www.opencores.org/project,amber // +// // +// Description // +// Turns memory access requests from the execute stage and // +// cache into wishbone bus cycles. For 4-word read requests // +// from the cache and swap accesses ( read followed by write // +// to the same address) from the execute stage, // +// a block transfer is done. All other requests result in // +// single word transfers. // +// // +// Write accesses can be done in a single clock cycle on // +// the wishbone bus, is the destination allows it. The // +// next transfer will begin immediately on the // +// next cycle on the bus. This looks like a block transfer // +// and does hold ownership of the wishbone bus, preventing // +// the other master ( the ethernet MAC) from gaining // +// ownership between those two cycles. But otherwise it would // +// be necessary to insert a wait cycle after every write, // +// slowing down the performance of the core by around 5 to // +// 10%. // +// // +// Author(s): // +// - Conor Santifort, csantifort.amber@gmail.com // +// // +////////////////////////////////////////////////////////////////// +// // +// Copyright (C) 2010 Authors and OPENCORES.ORG // +// // +// This source file may be used and distributed without // +// restriction provided that this copyright statement is not // +// removed from the file and that any derivative work contains // +// the original copyright notice and the associated disclaimer. // +// // +// This source file is free software; you can redistribute it // +// and/or modify it under the terms of the GNU Lesser General // +// Public License as published by the Free Software Foundation; // +// either version 2.1 of the License, or (at your option) any // +// later version. // +// // +// This source 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 Lesser General Public License for more // +// details. // +// // +// You should have received a copy of the GNU Lesser General // +// Public License along with this source; if not, download it // +// from http://www.opencores.org/lgpl.shtml // +// // +////////////////////////////////////////////////////////////////// + + +module a23_wishbone +( +input i_clk, + +// Core Accesses to Wishbone bus +input i_select, +input [31:0] i_write_data, +input i_write_enable, +input [3:0] i_byte_enable, // valid for writes only +input i_data_access, +input i_exclusive, // high for read part of swap access +input [31:0] i_address, +input i_translate, // assert the translate pin from the core. +output o_stall, +output o_abort, + +// Cache Accesses to Wishbone bus +input i_cache_req, + +// Wishbone Bus +output reg [31:0] o_wb_adr, +output reg [3:0] o_wb_sel, +output reg o_wb_we , +input [31:0] i_wb_dat, +output reg [31:0] o_wb_dat, +output reg o_wb_cyc, +output reg o_wb_stb, +input i_wb_ack, +input i_wb_err, +output reg o_wb_tga // address attributes + +); + + +localparam [3:0] WB_IDLE = 3'd0, + WB_BURST1 = 3'd1, + WB_BURST2 = 3'd2, + WB_BURST3 = 3'd3, + WB_WAIT_ACK = 3'd4; + +reg [2:0] wishbone_st = WB_IDLE; + +wire core_read_request; +wire core_write_request; +wire cache_read_request; +wire cache_write_request; +wire start_access; +reg servicing_cache = 'd0; +wire [3:0] byte_enable; +reg exclusive_access = 'd0; +wire read_ack; +wire wait_write_ack; +wire wb_wait; + +// Write buffer +reg [31:0] wbuf_addr_r = 'd0; +reg [3:0] wbuf_sel_r = 'd0; +reg wbuf_busy_r = 'd0; + + +assign read_ack = !o_wb_we && i_wb_ack; +wire write_ack = o_wb_we && i_wb_ack; +assign o_stall = ( core_write_request && !write_ack ) || + ( core_read_request && !read_ack ) || + ( core_read_request && servicing_cache ) || + ( core_write_request && servicing_cache ) || + ( cache_write_request && wishbone_st == WB_WAIT_ACK) || + wbuf_busy_r; + + // Don't stall on writes + // Wishbone is doing burst read so make core wait to execute the write + // ( core_write_request && !i_wb_ack ) ; + +assign core_read_request = i_select && !i_write_enable; +assign core_write_request = i_select && i_write_enable; + +assign cache_read_request = i_cache_req && !i_write_enable; +assign cache_write_request = i_cache_req && i_write_enable; + +assign wb_wait = o_wb_stb && !i_wb_ack; +assign start_access = (core_read_request || core_write_request || i_cache_req) && !wb_wait ; + +// For writes the byte enable is always 4'hf +assign byte_enable = wbuf_busy_r ? wbuf_sel_r : + ( core_write_request || cache_write_request ) ? i_byte_enable : + 4'hf ; + + + +// ====================================== +// Write buffer +// ====================================== + + +always @( posedge i_clk ) + if ( wb_wait && !wbuf_busy_r && (core_write_request || cache_write_request) ) + begin + wbuf_addr_r <= i_address; + wbuf_sel_r <= i_byte_enable; + wbuf_busy_r <= 1'd1; + end + else if (!o_wb_stb) + wbuf_busy_r <= 1'd0; + +// ====================================== +// Register Accesses +// ====================================== +always @( posedge i_clk ) + if ( start_access ) + o_wb_dat <= i_write_data; + + +assign wait_write_ack = o_wb_stb && o_wb_we && !i_wb_ack; + + +always @( posedge i_clk ) + case ( wishbone_st ) + WB_IDLE : + begin + + if ( start_access ) + begin + o_wb_stb <= 1'd1; + o_wb_cyc <= 1'd1; + o_wb_sel <= byte_enable; + o_wb_tga <= i_translate; + end + else if ( !wait_write_ack ) + begin + o_wb_stb <= 1'd0; + o_wb_tga <= 1'b0; + // Hold cyc high after an exclusive access + // to hold ownership of the wishbone bus + o_wb_cyc <= exclusive_access; + end + + // cache has priority over the core + servicing_cache <= cache_read_request && !wait_write_ack; + + if ( wait_write_ack ) + begin + // still waiting for last (write) access to complete + wishbone_st <= WB_WAIT_ACK; + end + // do a burst of 4 read to fill a cache line + else if ( cache_read_request ) + begin + wishbone_st <= WB_BURST1; + exclusive_access <= 1'd0; + end + else if ( core_read_request ) + begin + wishbone_st <= WB_WAIT_ACK; + exclusive_access <= i_exclusive; + end + // The core does not currently issue exclusive write requests + // but there's no reason why this might not be added some + // time in the future so allow for it here + else if ( core_write_request ) + exclusive_access <= i_exclusive; + + + if ( start_access ) + begin + if (wbuf_busy_r) + begin + o_wb_we <= 1'd1; + o_wb_adr[31:2] <= wbuf_addr_r[31:2]; + end + else + begin + o_wb_we <= core_write_request || cache_write_request; + // only update these on new wb access to make debug easier + o_wb_adr[31:2] <= i_address[31:2]; + end + + o_wb_adr[1:0] <= byte_enable == 4'b0001 ? 2'd0 : + byte_enable == 4'b0010 ? 2'd1 : + byte_enable == 4'b0100 ? 2'd2 : + byte_enable == 4'b1000 ? 2'd3 : + + byte_enable == 4'b0011 ? 2'd0 : + byte_enable == 4'b1100 ? 2'd2 : + + i_address[1:0]; + end + end + + + // Read burst, wait for first ack + WB_BURST1: + if ( i_wb_ack ) + begin + // burst of 4 that wraps + o_wb_adr[3:2] <= o_wb_adr[3:2] + 1'd1; + wishbone_st <= WB_BURST2; + end + + + // Read burst, wait for second ack + WB_BURST2: + if ( i_wb_ack ) + begin + // burst of 4 that wraps + o_wb_adr[3:2] <= o_wb_adr[3:2] + 1'd1; + wishbone_st <= WB_BURST3; + end + + + // Read burst, wait for third ack + WB_BURST3: + if ( i_wb_ack ) + begin + // burst of 4 that wraps + o_wb_adr[3:2] <= o_wb_adr[3:2] + 1'd1; + wishbone_st <= WB_WAIT_ACK; + end + + + // Wait for the wishbone ack to be asserted + WB_WAIT_ACK: + if ( i_wb_ack | i_wb_err) + begin + wishbone_st <= WB_IDLE; + o_wb_stb <= 1'd0; + o_wb_cyc <= exclusive_access; + o_wb_we <= 1'd0; + servicing_cache <= 1'd0; + end + + endcase + + +assign o_abort = i_wb_err & o_wb_cyc; + +// ======================================================== +// Debug Wishbone bus - not synthesizable +// ======================================================== +//synopsys translate_off +wire [(14*8)-1:0] xAS_STATE; + + +assign xAS_STATE = wishbone_st == WB_IDLE ? "WB_IDLE" : + wishbone_st == WB_BURST1 ? "WB_BURST1" : + wishbone_st == WB_BURST2 ? "WB_BURST2" : + wishbone_st == WB_BURST3 ? "WB_BURST3" : + wishbone_st == WB_WAIT_ACK ? "WB_WAIT_ACK" : + "UNKNOWN" ; + +//synopsys translate_on + +initial begin + + o_wb_adr = 32'd0; + o_wb_sel = 4'd0; + o_wb_we = 1'd0; + o_wb_dat = 32'd0; + o_wb_cyc = 1'd0; + o_wb_stb = 1'd0; + o_wb_tga = 1'b0; + +end +endmodule + diff --git a/amber/debug_functions.v b/amber/debug_functions.v new file mode 100644 index 0000000..e63cdee --- /dev/null +++ b/amber/debug_functions.v @@ -0,0 +1,228 @@ +////////////////////////////////////////////////////////////////// +// // +// Debug Functions // +// // +// This file is part of the Amber project // +// http://www.opencores.org/project,amber // +// // +// Description // +// A bunch of non-synthesizable testbench functions // +// // +// Author(s): // +// - Conor Santifort, csantifort.amber@gmail.com // +// // +////////////////////////////////////////////////////////////////// +// // +// Copyright (C) 2010 Authors and OPENCORES.ORG // +// // +// This source file may be used and distributed without // +// restriction provided that this copyright statement is not // +// removed from the file and that any derivative work contains // +// the original copyright notice and the associated disclaimer. // +// // +// This source file is free software; you can redistribute it // +// and/or modify it under the terms of the GNU Lesser General // +// Public License as published by the Free Software Foundation; // +// either version 2.1 of the License, or (at your option) any // +// later version. // +// // +// This source 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 Lesser General Public License for more // +// details. // +// // +// You should have received a copy of the GNU Lesser General // +// Public License along with this source; if not, download it // +// from http://www.opencores.org/lgpl.shtml // +// // +////////////////////////////////////////////////////////////////// + +// Testbench Functions used in more than one module + + +function [31:0] hex_chars_to_32bits; +input [8*8-1:0] hex_chars; +begin +hex_chars_to_32bits[31:28] = hex_chars_to_4bits (hex_chars[8*8-1:7*8]); +hex_chars_to_32bits[27:24] = hex_chars_to_4bits (hex_chars[7*8-1:6*8]); +hex_chars_to_32bits[23:20] = hex_chars_to_4bits (hex_chars[6*8-1:5*8]); +hex_chars_to_32bits[19:16] = hex_chars_to_4bits (hex_chars[5*8-1:4*8]); +hex_chars_to_32bits[15:12] = hex_chars_to_4bits (hex_chars[4*8-1:3*8]); +hex_chars_to_32bits[11: 8] = hex_chars_to_4bits (hex_chars[3*8-1:2*8]); +hex_chars_to_32bits[ 7: 4] = hex_chars_to_4bits (hex_chars[2*8-1:1*8]); +hex_chars_to_32bits[ 3: 0] = hex_chars_to_4bits (hex_chars[1*8-1: 0]); +end +endfunction + + +function [7:0] hex_chars_to_8bits; +input [8*2-1:0] hex_chars; +begin +hex_chars_to_8bits[ 7: 4] = hex_chars_to_4bits (hex_chars[2*8-1:1*8]); +hex_chars_to_8bits[ 3: 0] = hex_chars_to_4bits (hex_chars[1*8-1: 0]); +end +endfunction + + +function [3:0] hex_chars_to_4bits; +input [7:0] hex_chars; +begin +case (hex_chars) + "0" : hex_chars_to_4bits = 4'h0; + "1" : hex_chars_to_4bits = 4'h1; + "2" : hex_chars_to_4bits = 4'h2; + "3" : hex_chars_to_4bits = 4'h3; + "4" : hex_chars_to_4bits = 4'h4; + "5" : hex_chars_to_4bits = 4'h5; + "6" : hex_chars_to_4bits = 4'h6; + "7" : hex_chars_to_4bits = 4'h7; + "8" : hex_chars_to_4bits = 4'h8; + "9" : hex_chars_to_4bits = 4'h9; + "a" : hex_chars_to_4bits = 4'ha; + "b" : hex_chars_to_4bits = 4'hb; + "c" : hex_chars_to_4bits = 4'hc; + "d" : hex_chars_to_4bits = 4'hd; + "e" : hex_chars_to_4bits = 4'he; + "f" : hex_chars_to_4bits = 4'hf; + "A" : hex_chars_to_4bits = 4'ha; + "B" : hex_chars_to_4bits = 4'hb; + "C" : hex_chars_to_4bits = 4'hc; + "D" : hex_chars_to_4bits = 4'hd; + "E" : hex_chars_to_4bits = 4'he; + "F" : hex_chars_to_4bits = 4'hf; +endcase +end +endfunction + + +function [120*8-1:0] align_line; +input [120*8-1:0] line; +begin +case (1'd1) + line[1 *8-1: 0] == 8'd0 : align_line = 960'd0; + line[2 *8-1:1 *8] == 8'd0 : align_line = {line[1 *8-1: 0], 952'd0}; + line[3 *8-1:2 *8] == 8'd0 : align_line = {line[2 *8-1: 0], 944'd0}; + line[4 *8-1:3 *8] == 8'd0 : align_line = {line[3 *8-1: 0], 936'd0}; + line[5 *8-1:4 *8] == 8'd0 : align_line = {line[4 *8-1: 0], 928'd0}; + line[6 *8-1:5 *8] == 8'd0 : align_line = {line[5 *8-1: 0], 920'd0}; + line[7 *8-1:6 *8] == 8'd0 : align_line = {line[6 *8-1: 0], 912'd0}; + line[8 *8-1:7 *8] == 8'd0 : align_line = {line[7 *8-1: 0], 904'd0}; + line[9 *8-1:8 *8] == 8'd0 : align_line = {line[8 *8-1: 0], 896'd0}; + line[10 *8-1:9 *8] == 8'd0 : align_line = {line[9 *8-1: 0], 888'd0}; + line[11 *8-1:10 *8] == 8'd0 : align_line = {line[10 *8-1: 0], 880'd0}; + line[12 *8-1:11 *8] == 8'd0 : align_line = {line[11 *8-1: 0], 872'd0}; + line[13 *8-1:12 *8] == 8'd0 : align_line = {line[12 *8-1: 0], 864'd0}; + line[14 *8-1:13 *8] == 8'd0 : align_line = {line[13 *8-1: 0], 856'd0}; + line[15 *8-1:14 *8] == 8'd0 : align_line = {line[14 *8-1: 0], 848'd0}; + line[16 *8-1:15 *8] == 8'd0 : align_line = {line[15 *8-1: 0], 840'd0}; + line[17 *8-1:16 *8] == 8'd0 : align_line = {line[16 *8-1: 0], 832'd0}; + line[18 *8-1:17 *8] == 8'd0 : align_line = {line[17 *8-1: 0], 824'd0}; + line[19 *8-1:18 *8] == 8'd0 : align_line = {line[18 *8-1: 0], 816'd0}; + line[20 *8-1:19 *8] == 8'd0 : align_line = {line[19 *8-1: 0], 808'd0}; + line[21 *8-1:20 *8] == 8'd0 : align_line = {line[20 *8-1: 0], 800'd0}; + line[22 *8-1:21 *8] == 8'd0 : align_line = {line[21 *8-1: 0], 792'd0}; + line[23 *8-1:22 *8] == 8'd0 : align_line = {line[22 *8-1: 0], 784'd0}; + line[24 *8-1:23 *8] == 8'd0 : align_line = {line[23 *8-1: 0], 776'd0}; + line[25 *8-1:24 *8] == 8'd0 : align_line = {line[24 *8-1: 0], 768'd0}; + line[26 *8-1:25 *8] == 8'd0 : align_line = {line[25 *8-1: 0], 760'd0}; + line[27 *8-1:26 *8] == 8'd0 : align_line = {line[26 *8-1: 0], 752'd0}; + line[28 *8-1:27 *8] == 8'd0 : align_line = {line[27 *8-1: 0], 744'd0}; + line[29 *8-1:28 *8] == 8'd0 : align_line = {line[28 *8-1: 0], 736'd0}; + line[30 *8-1:29 *8] == 8'd0 : align_line = {line[29 *8-1: 0], 728'd0}; + line[31 *8-1:30 *8] == 8'd0 : align_line = {line[30 *8-1: 0], 720'd0}; + line[32 *8-1:31 *8] == 8'd0 : align_line = {line[31 *8-1: 0], 712'd0}; + line[33 *8-1:32 *8] == 8'd0 : align_line = {line[32 *8-1: 0], 704'd0}; + line[34 *8-1:33 *8] == 8'd0 : align_line = {line[33 *8-1: 0], 696'd0}; + line[35 *8-1:34 *8] == 8'd0 : align_line = {line[34 *8-1: 0], 688'd0}; + line[36 *8-1:35 *8] == 8'd0 : align_line = {line[35 *8-1: 0], 680'd0}; + line[37 *8-1:36 *8] == 8'd0 : align_line = {line[36 *8-1: 0], 672'd0}; + line[38 *8-1:37 *8] == 8'd0 : align_line = {line[37 *8-1: 0], 664'd0}; + line[39 *8-1:38 *8] == 8'd0 : align_line = {line[38 *8-1: 0], 656'd0}; + line[40 *8-1:39 *8] == 8'd0 : align_line = {line[39 *8-1: 0], 648'd0}; + line[41 *8-1:40 *8] == 8'd0 : align_line = {line[40 *8-1: 0], 640'd0}; + line[42 *8-1:41 *8] == 8'd0 : align_line = {line[41 *8-1: 0], 632'd0}; + line[43 *8-1:42 *8] == 8'd0 : align_line = {line[42 *8-1: 0], 624'd0}; + line[44 *8-1:43 *8] == 8'd0 : align_line = {line[43 *8-1: 0], 616'd0}; + line[45 *8-1:44 *8] == 8'd0 : align_line = {line[44 *8-1: 0], 608'd0}; + line[46 *8-1:45 *8] == 8'd0 : align_line = {line[45 *8-1: 0], 600'd0}; + line[47 *8-1:46 *8] == 8'd0 : align_line = {line[46 *8-1: 0], 592'd0}; + line[48 *8-1:47 *8] == 8'd0 : align_line = {line[47 *8-1: 0], 584'd0}; + line[49 *8-1:48 *8] == 8'd0 : align_line = {line[48 *8-1: 0], 576'd0}; + line[50 *8-1:49 *8] == 8'd0 : align_line = {line[49 *8-1: 0], 568'd0}; + line[51 *8-1:50 *8] == 8'd0 : align_line = {line[50 *8-1: 0], 560'd0}; + line[52 *8-1:51 *8] == 8'd0 : align_line = {line[51 *8-1: 0], 552'd0}; + line[53 *8-1:52 *8] == 8'd0 : align_line = {line[52 *8-1: 0], 544'd0}; + line[54 *8-1:53 *8] == 8'd0 : align_line = {line[53 *8-1: 0], 536'd0}; + line[55 *8-1:54 *8] == 8'd0 : align_line = {line[54 *8-1: 0], 528'd0}; + line[56 *8-1:55 *8] == 8'd0 : align_line = {line[55 *8-1: 0], 520'd0}; + line[57 *8-1:56 *8] == 8'd0 : align_line = {line[56 *8-1: 0], 512'd0}; + line[58 *8-1:57 *8] == 8'd0 : align_line = {line[57 *8-1: 0], 504'd0}; + line[59 *8-1:58 *8] == 8'd0 : align_line = {line[58 *8-1: 0], 496'd0}; + line[60 *8-1:59 *8] == 8'd0 : align_line = {line[59 *8-1: 0], 488'd0}; + line[61 *8-1:60 *8] == 8'd0 : align_line = {line[60 *8-1: 0], 480'd0}; + line[62 *8-1:61 *8] == 8'd0 : align_line = {line[61 *8-1: 0], 472'd0}; + line[63 *8-1:62 *8] == 8'd0 : align_line = {line[62 *8-1: 0], 464'd0}; + line[64 *8-1:63 *8] == 8'd0 : align_line = {line[63 *8-1: 0], 456'd0}; + line[65 *8-1:64 *8] == 8'd0 : align_line = {line[64 *8-1: 0], 448'd0}; + line[66 *8-1:65 *8] == 8'd0 : align_line = {line[65 *8-1: 0], 440'd0}; + line[67 *8-1:66 *8] == 8'd0 : align_line = {line[66 *8-1: 0], 432'd0}; + line[68 *8-1:67 *8] == 8'd0 : align_line = {line[67 *8-1: 0], 424'd0}; + line[69 *8-1:68 *8] == 8'd0 : align_line = {line[68 *8-1: 0], 416'd0}; + line[70 *8-1:69 *8] == 8'd0 : align_line = {line[69 *8-1: 0], 408'd0}; + line[71 *8-1:70 *8] == 8'd0 : align_line = {line[70 *8-1: 0], 400'd0}; + line[72 *8-1:71 *8] == 8'd0 : align_line = {line[71 *8-1: 0], 392'd0}; + line[73 *8-1:72 *8] == 8'd0 : align_line = {line[72 *8-1: 0], 384'd0}; + line[74 *8-1:73 *8] == 8'd0 : align_line = {line[73 *8-1: 0], 376'd0}; + line[75 *8-1:74 *8] == 8'd0 : align_line = {line[74 *8-1: 0], 368'd0}; + line[76 *8-1:75 *8] == 8'd0 : align_line = {line[75 *8-1: 0], 360'd0}; + line[77 *8-1:76 *8] == 8'd0 : align_line = {line[76 *8-1: 0], 352'd0}; + line[78 *8-1:77 *8] == 8'd0 : align_line = {line[77 *8-1: 0], 344'd0}; + line[79 *8-1:78 *8] == 8'd0 : align_line = {line[78 *8-1: 0], 336'd0}; + line[80 *8-1:79 *8] == 8'd0 : align_line = {line[79 *8-1: 0], 328'd0}; + line[81 *8-1:80 *8] == 8'd0 : align_line = {line[80 *8-1: 0], 320'd0}; + line[82 *8-1:81 *8] == 8'd0 : align_line = {line[81 *8-1: 0], 312'd0}; + line[83 *8-1:82 *8] == 8'd0 : align_line = {line[82 *8-1: 0], 304'd0}; + line[84 *8-1:83 *8] == 8'd0 : align_line = {line[83 *8-1: 0], 296'd0}; + line[85 *8-1:84 *8] == 8'd0 : align_line = {line[84 *8-1: 0], 288'd0}; + line[86 *8-1:85 *8] == 8'd0 : align_line = {line[85 *8-1: 0], 280'd0}; + line[87 *8-1:86 *8] == 8'd0 : align_line = {line[86 *8-1: 0], 272'd0}; + line[88 *8-1:87 *8] == 8'd0 : align_line = {line[87 *8-1: 0], 264'd0}; + line[89 *8-1:88 *8] == 8'd0 : align_line = {line[88 *8-1: 0], 256'd0}; + line[90 *8-1:89 *8] == 8'd0 : align_line = {line[89 *8-1: 0], 248'd0}; + line[91 *8-1:90 *8] == 8'd0 : align_line = {line[90 *8-1: 0], 240'd0}; + line[92 *8-1:91 *8] == 8'd0 : align_line = {line[91 *8-1: 0], 232'd0}; + line[93 *8-1:92 *8] == 8'd0 : align_line = {line[92 *8-1: 0], 224'd0}; + line[94 *8-1:93 *8] == 8'd0 : align_line = {line[93 *8-1: 0], 216'd0}; + line[95 *8-1:94 *8] == 8'd0 : align_line = {line[94 *8-1: 0], 208'd0}; + line[96 *8-1:95 *8] == 8'd0 : align_line = {line[95 *8-1: 0], 200'd0}; + line[97 *8-1:96 *8] == 8'd0 : align_line = {line[96 *8-1: 0], 192'd0}; + line[98 *8-1:97 *8] == 8'd0 : align_line = {line[97 *8-1: 0], 184'd0}; + line[99 *8-1:98 *8] == 8'd0 : align_line = {line[98 *8-1: 0], 176'd0}; + line[100*8-1:99 *8] == 8'd0 : align_line = {line[99 *8-1: 0], 168'd0}; + line[101*8-1:100*8] == 8'd0 : align_line = {line[100*8-1: 0], 160'd0}; + line[102*8-1:101*8] == 8'd0 : align_line = {line[101*8-1: 0], 152'd0}; + line[103*8-1:102*8] == 8'd0 : align_line = {line[102*8-1: 0], 144'd0}; + line[104*8-1:103*8] == 8'd0 : align_line = {line[103*8-1: 0], 136'd0}; + line[105*8-1:104*8] == 8'd0 : align_line = {line[104*8-1: 0], 128'd0}; + line[106*8-1:105*8] == 8'd0 : align_line = {line[105*8-1: 0], 120'd0}; + line[107*8-1:106*8] == 8'd0 : align_line = {line[106*8-1: 0], 112'd0}; + line[108*8-1:107*8] == 8'd0 : align_line = {line[107*8-1: 0], 104'd0}; + line[109*8-1:108*8] == 8'd0 : align_line = {line[108*8-1: 0], 96'd0}; + line[110*8-1:109*8] == 8'd0 : align_line = {line[109*8-1: 0], 88'd0}; + line[111*8-1:110*8] == 8'd0 : align_line = {line[110*8-1: 0], 80'd0}; + line[112*8-1:111*8] == 8'd0 : align_line = {line[111*8-1: 0], 72'd0}; + line[113*8-1:112*8] == 8'd0 : align_line = {line[112*8-1: 0], 64'd0}; + line[114*8-1:113*8] == 8'd0 : align_line = {line[113*8-1: 0], 56'd0}; + line[115*8-1:114*8] == 8'd0 : align_line = {line[114*8-1: 0], 48'd0}; + line[116*8-1:115*8] == 8'd0 : align_line = {line[115*8-1: 0], 40'd0}; + line[117*8-1:116*8] == 8'd0 : align_line = {line[116*8-1: 0], 32'd0}; + line[118*8-1:117*8] == 8'd0 : align_line = {line[117*8-1: 0], 24'd0}; + line[119*8-1:118*8] == 8'd0 : align_line = {line[118*8-1: 0], 16'd0}; + line[120*8-1:119*8] == 8'd0 : align_line = {line[119*8-1: 0], 8'd0}; + + default: align_line = 960'd0; +endcase +end +endfunction + diff --git a/amber/memory_configuration.v b/amber/memory_configuration.v new file mode 100644 index 0000000..c4c2769 --- /dev/null +++ b/amber/memory_configuration.v @@ -0,0 +1,81 @@ +////////////////////////////////////////////////////////////////// +// // +// Memory configuration and Wishbone address decoding // +// // +// This file is part of the Amber project // +// http://www.opencores.org/project,amber // +// // +// Description // +// This module provides a set of functions that are used to // +// decode memory addresses so other modules know if an address // +// is for example in main memory, or boot memory, or a UART // +// // +// Author(s): // +// - Conor Santifort, csantifort.amber@gmail.com // +// // +////////////////////////////////////////////////////////////////// +// // +// Copyright (C) 2010 Authors and OPENCORES.ORG // +// // +// This source file may be used and distributed without // +// restriction provided that this copyright statement is not // +// removed from the file and that any derivative work contains // +// the original copyright notice and the associated disclaimer. // +// // +// This source file is free software; you can redistribute it // +// and/or modify it under the terms of the GNU Lesser General // +// Public License as published by the Free Software Foundation; // +// either version 2.1 of the License, or (at your option) any // +// later version. // +// // +// This source 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 Lesser General Public License for more // +// details. // +// // +// You should have received a copy of the GNU Lesser General // +// Public License along with this source; if not, download it // +// from http://www.opencores.org/lgpl.shtml // +// // +////////////////////////////////////////////////////////////////// + +// e.g. 24 for 32MBytes, 26 for 128MBytes +localparam MAIN_MSB = 26; + +// e.g. 13 for 4k words +localparam BOOT_MSB = 13; + +localparam MAIN_BASE = 32'h0000_0000; /* Main Memory */ +localparam PHYS_BASE = 32'h0200_0000; /* Physical Memory */ +localparam IO_BASE = 32'h0300_0000; /* Physical Memory */ +localparam ROM_BASE = 32'h0340_0000; /* Uncachable Boot Memory */ +localparam ROM_TOP = 32'h0400_0000; /* Uncachable Boot Memory */ + +function in_rom_mem; + input [31:0] address; +begin +in_rom_mem = (address >= ROM_BASE && + address < (ROM_TOP)); +end +endfunction + + +function in_main_mem; + input [31:0] address; +begin +in_main_mem = (address >= MAIN_BASE && + address < (IO_BASE)); +end +endfunction + + +// Used in fetch.v and l2cache.v to allow accesses to these addresses +// to be cached +function in_cachable_mem; + input [31:0] address; +begin + in_cachable_mem = 0; +end +endfunction + diff --git a/archimedes_top.v b/archimedes_top.v new file mode 100644 index 0000000..cbd773b --- /dev/null +++ b/archimedes_top.v @@ -0,0 +1,387 @@ +`timescale 1ns / 1ps +// archimedes_top.v +// +// Archimedes top +// +// Copyright (c) 2014 Stephen J. Leary +// +// 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 archimedes_top( + + // base CPU Clock + input CLKCPU_I, + input CLKPIX_I, + output CEPIX_O, + + input RESET_I, + + // cpu wishbone interface. + output MEM_CYC_O, + output MEM_STB_O, + output MEM_WE_O, + + input MEM_ACK_I, + input MEM_ERR_I, + input MEM_RTY_I, + + output [3:0] MEM_SEL_O, + output [2:0] MEM_CTI_O, + output [23:2] MEM_ADDR_O, + + input [31:0] MEM_DAT_I, + output [31:0] MEM_DAT_O, + + // video signals (VGA) + output HSYNC, + output VSYNC, + + output [3:0] VIDEO_R, + output [3:0] VIDEO_G, + output [3:0] VIDEO_B, + output VIDEO_EN, + + // VIDC Enhancer selection. + // These are from external latch C + output [1:0] VIDBASECLK_O, + output [1:0] VIDSYNCPOL_O, + + // I2C bus to the CMOS. + output I2C_DOUT, + input I2C_DIN, + output I2C_CLOCK, + + // "Floppy" LED + output DEBUG_LED, + + // floppy connections to external controller + output [31:0] FDC_DIO_STATUS_OUT, + input [31:0] FDC_DIO_STATUS_IN, + input [7:0] FDC_DIN, + input FDC_DIN_STROBE, + + // connection to keyboard controller + output [7:0] KBD_OUT_DATA, + output KBD_OUT_STROBE, + input [7:0] KBD_IN_DATA, + input KBD_IN_STROBE, + + input [4:0] JOYSTICK0, + input [4:0] JOYSTICK1, + + // audio signal. + output [15:0] AUDIO_L, + output [15:0] AUDIO_R + +); + +// cpu bus +(*KEEP="TRUE"*)wire [31:0] cpu_address /* synthesis keep */; +(*KEEP="TRUE"*)wire [3:0] cpu_sel /* synthesis keep */ ; + + +(*KEEP="TRUE"*)wire cpu_spvmd/* synthesis keep */ ; +(*KEEP="TRUE"*)wire [31:0] cpu_dat_o/* synthesis keep */ ; +(*KEEP="TRUE"*)wire [31:0] cpu_dat_i/* synthesis keep */ ; + +(*KEEP="TRUE"*)wire cpu_cyc/* synthesis keep */ ; +(*KEEP="TRUE"*)wire cpu_stb/* synthesis keep */ ; +(*KEEP="TRUE"*)wire cpu_we/* synthesis keep */ ; + +(*KEEP="TRUE"*)wire cpu_ack/* synthesis keep */ ; +(*KEEP="TRUE"*)wire cpu_err/* synthesis keep */ ; +(*KEEP="TRUE"*)wire cpu_irq/* synthesis keep */ ; +(*KEEP="TRUE"*)wire cpu_firq/* synthesis keep */ ; + +// video DMA signals. +(*KEEP="TRUE"*)wire [31:0] vid_address; // VIDC D31-D0 +(*KEEP="TRUE"*)wire vid_flybk /* synthesis keep */; // VIDC FLYBK +(*KEEP="TRUE"*)wire vid_req; // VIDC REQ +(*KEEP="TRUE"*)wire vid_ack; // VIDC ACK + +(*KEEP="TRUE"*)wire ioc_cs/* synthesis keep */ ; +(*KEEP="TRUE"*)wire ioc_ack/* synthesis keep */ ; +(*KEEP="TRUE"*)wire [7:0] ioc_dat_o/* synthesis keep */ ; + +(*KEEP="TRUE"*)wire rom_low_cs/* synthesis keep */ ; +wire [5:0] ioc_cin, ioc_cout; + +a23_core ARM( + + .i_clk ( CLKCPU_I ), + + .o_wb_cyc ( cpu_cyc ), + .o_wb_stb ( cpu_stb ), + .o_wb_we ( cpu_we ), + + .o_wb_adr ( cpu_address ), + .o_wb_sel ( cpu_sel ), + + .i_wb_dat ( cpu_dat_i ), + .o_wb_dat ( cpu_dat_o ), + + + .i_wb_ack ( cpu_ack ), + .i_wb_err ( cpu_err ), + + .o_wb_tga ( cpu_spvmd ), + .i_irq ( cpu_irq ), + .i_firq ( cpu_firq ), + + .i_system_rdy(~RESET_I ) +); + +wire sirq_n; +wire ram_cs; +wire vid_we; +wire snd_ack, snd_req; + +memc MEMC( + + .clkcpu ( CLKCPU_I ), + .rst_i ( RESET_I ), + + .spvmd ( cpu_spvmd ), + + // cpu interface + .cpu_address ( cpu_address[25:0] ), + .cpu_cyc ( cpu_cyc ), + .cpu_stb ( cpu_stb ), + .cpu_we ( cpu_we ), + .cpu_sel ( cpu_sel ), + .cpu_ack ( cpu_ack ), + .cpu_err ( cpu_err ), + + // memory interface + .mem_addr_o ( MEM_ADDR_O ), + .mem_stb_o ( MEM_STB_O ), + .mem_cyc_o ( MEM_CYC_O ), + .mem_ack_i ( MEM_ACK_I ), + .mem_sel_o ( MEM_SEL_O ), + .mem_we_o ( MEM_WE_O ), + .mem_cti_o ( MEM_CTI_O ), + + // vidc interface + .hsync ( HSYNC ), + .flybk ( vid_flybk ), + .vidrq ( vid_req ), + .vidak ( vid_ack ), + .sndak ( snd_ack ), + .sndrq ( snd_req ), + .vidw ( vid_we ), + + // ioc interface + .ioc_cs ( ioc_cs ), + .rom_low_cs ( rom_low_cs ), + .ram_cs ( ram_cs ), + + // irqs + + .sirq_n ( sirq_n ) +); + +vidc VIDC( + + .clkpix ( CLKPIX_I ), + .cepix ( CEPIX_O ), + + .clkcpu ( CLKCPU_I ), + .rst_i ( RESET_I), + + .cpu_dat ( cpu_dat_o ), + + // memc + .flybk ( vid_flybk ), + .vidak ( vid_ack ), + .vidrq ( vid_req ), + .sndak ( snd_ack ), + .sndrq ( snd_req ), + + .viddat ( MEM_DAT_I ), + .vidw ( vid_we ), + + // video signals + .hsync ( HSYNC ), + .vsync ( VSYNC ), + .video_r ( VIDEO_R ), + .video_g ( VIDEO_G ), + .video_b ( VIDEO_B ), + .video_en ( VIDEO_EN ), + + // audio signals + .audio_l ( AUDIO_L ), + .audio_r ( AUDIO_R ) +); + +wire [1:0] ioc_speed = cpu_address[20:19]; +wire [7:1] ioc_select; +wire ioc_sext; +// podule data bus. +wire [15:0] pod_dat_o; +wire [15:0] pod_dat_i; + +wire floppy_firq; +wire floppy_drq; + +wire ioc_clk2m_en, ioc_clk8m_en; + +ioc IOC( + + .clkcpu ( CLKCPU_I ), + .clk2m_en ( ioc_clk2m_en ), + .clk8m_en ( ioc_clk8m_en ), + + .por ( RESET_I ), + .ir ( vid_flybk ), + + .fh ( {floppy_firq, floppy_drq}), + + .il ( {6'b1111, sirq_n, 1'b1 }), + + .c_in ( ioc_cin ), + .c_out ( ioc_cout ), + + .select ( ioc_select ), + .sext ( ioc_sext ), + + // wishbone bus + .wb_adr ( cpu_address[6:2] ), + .wb_stb ( cpu_stb & cpu_address[21] & ioc_cs ), + .wb_cyc ( cpu_cyc & cpu_address[21] & ioc_cs ), + .wb_we ( cpu_we ), + + .wb_dat_i ( cpu_dat_o[23:16] ), + .wb_dat_o ( ioc_dat_o ), + .wb_bank ( cpu_address[18:16] ), + + .irq ( cpu_irq ), + .firq ( cpu_firq ), + + .kbd_out_data ( KBD_OUT_DATA ), + .kbd_out_strobe( KBD_OUT_STROBE ), + .kbd_in_data ( KBD_IN_DATA ), + .kbd_in_strobe ( KBD_IN_STROBE ) +); + +wire podules_en = ioc_cs & ioc_select[4]; + +// all podules live in the the podules module. +// this is just to keep things tidy. +podules PODULES( + // everything is synced to the master 32m clock except the pix clock. + .clkcpu ( CLKCPU_I ), + .clk2m_en ( ioc_clk2m_en ), + .clk8m_en ( ioc_clk8m_en ), + + .rst_i ( RESET_I ), + + .speed_i ( ioc_speed ), + + .wb_cyc ( cpu_cyc & podules_en), + .wb_stb ( cpu_stb & podules_en), + .wb_we ( cpu_we & podules_en), + + .wb_dat_o ( pod_dat_o ), + .wb_dat_i ( cpu_dat_o[15:0] ), + .wb_adr ( cpu_address[15:2] ) +); + +wire [7:0] floppy_dat_o; +wire floppy_en = ioc_cs & ioc_select[1]; + +// floppy drive signals. +wire [3:0] floppy_drive; +wire floppy_side; +wire floppy_motor; +wire floppy_inuse; +wire floppy_density; +wire floppy_reset; + +fdc1772 FDC1772 ( + + .clkcpu ( CLKCPU_I ), + .clk8m_en ( ioc_clk8m_en ), + + .wb_cyc ( cpu_cyc & floppy_en), + .wb_stb ( cpu_stb & floppy_en), + .wb_we ( cpu_we & floppy_en), + + .wb_dat_o ( floppy_dat_o ), + .wb_dat_i ( cpu_dat_o[23:16] ), + .wb_adr ( cpu_address[15:2] ), + + .floppy_firq ( floppy_firq ), + .floppy_drq ( floppy_drq ), + + .dio_status_out( FDC_DIO_STATUS_OUT ), + .dio_status_in ( FDC_DIO_STATUS_IN ), + .dio_in_strobe ( FDC_DIN_STROBE ), + .dio_in ( FDC_DIN ), + + .floppy_drive ( floppy_drive ), + .floppy_motor ( floppy_motor ), + .floppy_inuse ( floppy_inuse ), + .floppy_side ( floppy_side ), + .floppy_density( floppy_density ), + .floppy_reset ( floppy_reset ) +); + +wire [7:0] latches_dat_o; +wire latches_en = ioc_cs & ioc_select[5] & (ioc_speed == 2'd2); + +latches LATCHES( + + .clkcpu ( CLKCPU_I ), + + .wb_cyc ( cpu_cyc & latches_en ), + .wb_stb ( cpu_stb & latches_en ), + .wb_we ( cpu_we & latches_en ), + + .wb_dat_i ( cpu_dat_o[23:16] ), + .wb_dat_o ( latches_dat_o ), + .wb_adr ( cpu_address[15:2] ), + + .floppy_drive ( floppy_drive ), + .floppy_motor ( floppy_motor ), + .floppy_inuse ( floppy_inuse ), + .floppy_side ( floppy_side ), + .floppy_density ( floppy_density ), + .floppy_reset ( floppy_reset ), + + .joy0 ( JOYSTICK0 ), + .joy1 ( JOYSTICK1 ), + + .baseclk ( VIDBASECLK_O ), + .syncpol ( VIDSYNCPOL_O ) +); + + +assign MEM_DAT_O = cpu_dat_o; + +assign cpu_dat_i = floppy_en ? {24'd0, floppy_dat_o} : + latches_en ? {24'd0, latches_dat_o} : + podules_en ? {16'd0, pod_dat_o} : + ioc_cs & ~ioc_sext ? {24'd0, ioc_dat_o} : + ram_cs ? MEM_DAT_I : + 32'hFFFF_FFFF; + +assign I2C_CLOCK = ioc_cout[1]; +assign I2C_DOUT = ioc_cout[0]; + +assign ioc_cin[5:0] = {ioc_cout[5:2], I2C_CLOCK, I2C_DIN}; +assign DEBUG_LED = ~(~floppy_inuse & ~floppy_drive[0]); + + +endmodule // archimedes_top diff --git a/audio.v b/audio.v new file mode 100644 index 0000000..f3c5d3b --- /dev/null +++ b/audio.v @@ -0,0 +1,47 @@ +// +// audio.v +// +// Archie audio subsystem implementation for the MiST board +// http://code.google.com/p/mist-board/ +// +// Copyright (c) 2015 Stephen Leary +// +// 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 audio( + input rst, + input clk, // 32 MHz + + input [15:0] audio_data_r, + input [15:0] audio_data_l, + + output audio_r, + output audio_l +); + +sigma_delta_dac sigma_delta_dac_l ( + .DACout (audio_l), + .DACin (audio_data_l[15:0]), + .CLK (clk), + .RESET (rst) +); + +sigma_delta_dac sigma_delta_dac_r ( + .DACout (audio_r), + .DACin (audio_data_r[15:0]), + .CLK (clk), + .RESET (rst) +); + +endmodule \ No newline at end of file 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/cmos.mif b/cmos.mif new file mode 100644 index 0000000..25e6d39 --- /dev/null +++ b/cmos.mif @@ -0,0 +1,256 @@ +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +03 +00 +1b +6f +40 +20 +80 +15 +f3 +8e +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +0d +00 +00 +0f +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +75 +00 +fe +00 +eb +00 +08 +00 +00 +00 +00 +10 +50 +1d +0c +00 +2e +90 +02 +00 +00 +00 +00 +03 +0a +00 +01 +00 +00 +02 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +01 +00 +00 +01 +00 +00 +00 +00 +00 +00 +00 +00 +63 +13 +00 +00 +04 +91 +20 +01 +f3 +00 +00 +00 +ff +00 +00 +0a +00 +00 +00 +00 +f0 +a8 +c3 +00 +cf +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +38 +00 +01 +2e +7c +7b +7d +0a +50 +00 +80 +02 +00 +00 diff --git a/fdc1772.v b/fdc1772.v new file mode 100644 index 0000000..c63ec1c --- /dev/null +++ b/fdc1772.v @@ -0,0 +1,726 @@ +// +// fdc1772.v +// +// Copyright (c) 2015 Till Harbaum +// +// 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: +// - Don't directly set track register but control it with the step commands +// - 30ms settle time after step before data can be read +// - some parts are hard coded for archie floppy format (not dos) + +module fdc1772 ( + input clkcpu, // system cpu clock. + input clk8m_en, + + // external set signals + input [3:0] floppy_drive, + input floppy_side, + input floppy_motor, + input floppy_inuse, + input floppy_density, + input floppy_reset, + + // interrupts + output floppy_firq, // floppy fast irq + output floppy_drq, // data request interrupt + + // "wishbone bus" the ack is externally generated currently. + input wb_cyc, + input wb_stb, + input wb_we, + + input [15:2] wb_adr, // la + input [7:0] wb_dat_i, // bd + output reg [7:0] wb_dat_o, // bd + + // place any signals that need to be passed up to the top after here. + output [31:0] dio_status_out, + input [31:0] dio_status_in, + input dio_in_strobe, + input [7:0] dio_in +); + +localparam CLK = 8000000; + +wire clk8m = clkcpu & clk8m_en; + +// ------------------------------------------------------------------------- +// --------------------- IO controller status handling --------------------- +// ------------------------------------------------------------------------- + +// sector only needs 4 bits and track only needs 7 bits. We thus encode side and +// floppy_drive into the upper bits +assign dio_status_out = { 5'b10100, fifo_rptr==0, fifo_wptr==0, busy, + cmd, floppy_side, track[6:0], floppy_drive, sector[3:0] }; + +// input status encodes information about all four possible floppy drives +// in 4*8 bits +wire [7:0] floppy_status = + (floppy_drive == 4'b1110)?dio_status_in[31:24]: + (floppy_drive == 4'b1101)?dio_status_in[23:16]: + (floppy_drive == 4'b1011)?dio_status_in[15:8]: + (floppy_drive == 4'b0111)?dio_status_in[7:0]: + 8'h00; + +wire floppy_present = floppy_status[0]; +wire floppy_write_protected = 1'b1; // will be floppy_status[1] in the future + + +// ------------------------------------------------------------------------- +// ---------------------------- IRQ/DRQ handling --------------------------- +// ------------------------------------------------------------------------- +reg irq; +reg irq_set; + +// floppy_reset and read of status register clears irq +reg cpu_read_status; +always @(posedge clkcpu) + cpu_read_status <= wb_stb && wb_cyc && !wb_we && + (wb_adr[3:2] == FDC_REG_CMDSTATUS); + +wire irq_clr = !floppy_reset || cpu_read_status; + +always @(posedge irq_set or posedge irq_clr) begin + if(irq_clr) irq <= 1'b0; + else irq <= 1'b1; +end + +assign floppy_firq = irq; + +reg drq; +reg drq_set; + +reg cpu_read_data; +always @(posedge clkcpu) + cpu_read_data <= wb_stb && wb_cyc && !wb_we && + (wb_adr[3:2] == FDC_REG_DATA); + +wire drq_clr = !floppy_reset || cpu_read_data; + +always @(posedge drq_set or posedge drq_clr) begin + if(drq_clr) drq <= 1'b0; + else drq <= 1'b1; +end + +assign floppy_drq = drq; + +// ------------------------------------------------------------------------- +// -------------------- virtual floppy drive mechanics --------------------- +// ------------------------------------------------------------------------- + +// ------------------------------------------------------------------------- +// ------------------------------- floppy 0 -------------------------------- +// ------------------------------------------------------------------------- +wire fd0_index; +wire fd0_ready; +wire [6:0] fd0_track; +wire [3:0] fd0_sector; +wire fd0_sector_hdr; +wire fd0_sector_data; +wire fd0_dclk; + +floppy floppy0 ( + .clk ( clk8m ), + + // control signals into floppy + .select (!floppy_drive[0] ), + .motor_on ( motor_on ), + .step_in ( step_in ), + .step_out ( step_out ), + + // status signals generated by floppy + .dclk ( fd0_dclk ), + .track ( fd0_track ), + .sector ( fd0_sector ), + .sector_hdr ( fd0_sector_hdr ), + .sector_data ( fd0_sector_data ), + .ready ( fd0_ready ), + .index ( fd0_index ) +); + +// ------------------------------------------------------------------------- +// ------------------------------- floppy 1 -------------------------------- +// ------------------------------------------------------------------------- +wire fd1_index; +wire fd1_ready; +wire [6:0] fd1_track; +wire [3:0] fd1_sector; +wire fd1_sector_hdr; +wire fd1_sector_data; +wire fd1_dclk; + +floppy floppy1 ( + .clk ( clk8m ), + + // control signals into floppy + .select (!floppy_drive[1] ), + .motor_on ( motor_on ), + .step_in ( step_in ), + .step_out ( step_out ), + + // status signals generated by floppy + .dclk ( fd1_dclk ), + .track ( fd1_track ), + .sector ( fd1_sector ), + .sector_hdr ( fd1_sector_hdr ), + .sector_data ( fd1_sector_data ), + .ready ( fd1_ready ), + .index ( fd1_index ) +); + +// ------------------------------------------------------------------------- +// ------------------------------- floppy 2 -------------------------------- +// ------------------------------------------------------------------------- +wire fd2_index; +wire fd2_ready; +wire [6:0] fd2_track; +wire [3:0] fd2_sector; +wire fd2_sector_hdr; +wire fd2_sector_data; +wire fd2_dclk; + +floppy floppy2 ( + .clk ( clk8m ), + + // control signals into floppy + .select (!floppy_drive[2] ), + .motor_on ( motor_on ), + .step_in ( step_in ), + .step_out ( step_out ), + + // status signals generated by floppy + .dclk ( fd2_dclk ), + .track ( fd2_track ), + .sector ( fd2_sector ), + .sector_hdr ( fd2_sector_hdr ), + .sector_data ( fd2_sector_data ), + .ready ( fd2_ready ), + .index ( fd2_index ) +); + +// ------------------------------------------------------------------------- +// ------------------------------- floppy 3 -------------------------------- +// ------------------------------------------------------------------------- +wire fd3_index; +wire fd3_ready; +wire [6:0] fd3_track; +wire [3:0] fd3_sector; +wire fd3_sector_hdr; +wire fd3_sector_data; +wire fd3_dclk; + +floppy floppy3 ( + .clk ( clk8m ), + + // control signals into floppy + .select (!floppy_drive[3] ), + .motor_on ( motor_on ), + .step_in ( step_in ), + .step_out ( step_out ), + + // status signals generated by floppy + .dclk ( fd3_dclk ), + .track ( fd3_track ), + .sector ( fd3_sector ), + .sector_hdr ( fd3_sector_hdr ), + .sector_data ( fd3_sector_data ), + .ready ( fd3_ready ), + .index ( fd3_index ) +); + +// ------------------------------------------------------------------------- +// ----------------------------- floppy demux ------------------------------ +// ------------------------------------------------------------------------- + +wire fd_index = (!floppy_drive[0])?fd0_index: + (!floppy_drive[1])?fd1_index: + (!floppy_drive[2])?fd2_index: + (!floppy_drive[3])?fd3_index: + 1'b0; + +wire fd_ready = (!floppy_drive[0])?fd0_ready: + (!floppy_drive[1])?fd1_ready: + (!floppy_drive[2])?fd2_ready: + (!floppy_drive[3])?fd3_ready: + 1'b0; + +wire [6:0] fd_track = (!floppy_drive[0])?fd0_track: + (!floppy_drive[1])?fd1_track: + (!floppy_drive[2])?fd2_track: + (!floppy_drive[3])?fd3_track: + 7'd0; + +wire [3:0] fd_sector = (!floppy_drive[0])?fd0_sector: + (!floppy_drive[1])?fd1_sector: + (!floppy_drive[2])?fd2_sector: + (!floppy_drive[3])?fd3_sector: + 4'd0; + +wire fd_sector_hdr = (!floppy_drive[0])?fd0_sector_hdr: + (!floppy_drive[1])?fd1_sector_hdr: + (!floppy_drive[2])?fd2_sector_hdr: + (!floppy_drive[3])?fd3_sector_hdr: + 1'b0; + +wire fd_sector_data = (!floppy_drive[0])?fd0_sector_data: + (!floppy_drive[1])?fd1_sector_data: + (!floppy_drive[2])?fd2_sector_data: + (!floppy_drive[3])?fd3_sector_data: + 1'b0; + +wire fd_dclk = (!floppy_drive[0])?fd0_dclk: + (!floppy_drive[1])?fd1_dclk: + (!floppy_drive[2])?fd2_dclk: + (!floppy_drive[3])?fd3_dclk: + 1'b0; + +wire fd_track0 = (fd_track == 0); + +// ------------------------------------------------------------------------- +// ----------------------- internal state machines ------------------------- +// ------------------------------------------------------------------------- + +// --------------------------- Motor handling ------------------------------ + +// if motor is off and type 1 command with "spin up sequnce" bit 3 set +// is received then the command is executed after the motor has +// reached full speed for 5 rotations (800ms spin-up time + 5*200ms = +// 1.8sec) If the floppy is idle for 10 rotations (2 sec) then the +// motor is switched off again +localparam MOTOR_IDLE_COUNTER = 10; +reg [3:0] motor_timeout_index; +reg indexD; +reg busy; +reg step_in, step_out; +reg [3:0] motor_spin_up_sequence; + +// consider spin up done either if the motor is not supposed to spin at all or +// if it's supposed to run and has left the spin up sequence +wire motor_spin_up_done = (!motor_on) || (motor_on && (motor_spin_up_sequence == 0)); + +// ---------------------------- step handling ------------------------------ + +localparam STEP_PULSE_LEN = 1; +localparam STEP_PULSE_CLKS = (STEP_PULSE_LEN * CLK)/1000; +reg [15:0] step_pulse_cnt; + +// the step rate is only valid for command type I +wire [15:0] step_rate_clk = + (cmd[1:0]==2'b00)?(2*CLK/1000-1): // 2ms + (cmd[1:0]==2'b01)?(3*CLK/1000-1): // 3ms + (cmd[1:0]==2'b10)?(5*CLK/1000-1): // 5ms + (6*CLK/1000-1); // 6ms + +reg [15:0] step_rate_cnt; + +// flag indicating that a "step" is in progress +wire step_busy = (step_rate_cnt != 0); +reg [7:0] step_to; + +always @(posedge clk8m) begin + if(!floppy_reset) begin + motor_on <= 1'b0; + busy <= 1'b0; + step_in <= 1'b0; + step_out <= 1'b0; + irq_set <= 1'b0; + data_read_start_set <= 1'b0; + data_read_done_clr <= 1'b0; + end else begin + irq_set <= 1'b0; + data_read_start_set <= 1'b0; + data_read_done_clr <= 1'b0; + + // disable step signal after 1 msec + if(step_pulse_cnt != 0) + step_pulse_cnt <= step_pulse_cnt - 16'd1; + else begin + step_in <= 1'b0; + step_out <= 1'b0; + end + + // step rate timer + if(step_rate_cnt != 0) + step_rate_cnt <= step_rate_cnt - 16'd1; + + // just received a new command + if(cmd_rx) begin + busy <= 1'b1; + + // type I commands can wait for the disk to spin up + if(cmd_type_1 && cmd[3] && !motor_on) begin + motor_on <= 1'b1; + motor_spin_up_sequence <= 6; // wait for 6 full rotations + end + + // handle "forced interrupt" + if(cmd[7:4] == 4'b1101) begin + busy <= 1'b0; + if(cmd[3]) irq_set <= 1'b1; + end + end + + // execute command if motor is not supposed to be running or + // wait for motor spinup to finish + if(busy && motor_spin_up_done && !step_busy) begin + + // ------------------------ TYPE I ------------------------- + if(cmd_type_1) begin + // all type 1 commands are step commands and step_to has been set + if(fd_track == step_to) begin + busy <= 1'b0; // done if reached track 0 + motor_timeout_index <= MOTOR_IDLE_COUNTER - 1; + irq_set <= 1'b1; // emit irq when command done + end else begin + // do the step + if(step_to < fd_track) step_in <= 1'b1; + else step_out <= 1'b1; + + // update track register +// if( (!cmd[6] && !cmd[5]) || // restore/seek +// ((cmd[6] || cmd[5]) && cmd[4])) begin // step(in/out) with update flag +// if(step_to < fd_track) track <= track - 1'd0; +// else track <= track + 1'd0; +// end + + step_pulse_cnt <= STEP_PULSE_CLKS-1; + step_rate_cnt <= step_rate_clk; + end + end // if (cmd_type_1) + + // ------------------------ TYPE II ------------------------- + if(cmd_type_2) begin + if(!floppy_present) begin + // no image selected -> send irq immediately + busy <= 1'b0; + motor_timeout_index <= MOTOR_IDLE_COUNTER - 1; + irq_set <= 1'b1; // emit irq when command done + end else begin + // read sector + if(cmd[7:5] == 3'b100) begin + // we are busy until the right sector header passes under + // the head and the arm7 has delivered at least one byte + // (one byte is sufficient as the arm7 is much faster and + // all further bytes will arrive in time) + if(fd_ready && fd_sector_hdr && + (fd_sector == sector) && (fifo_wptr != 0)) + data_read_start_set <= 1'b1; + + if(data_read_done) begin + data_read_done_clr <= 1'b1; + busy <= 1'b0; + motor_timeout_index <= MOTOR_IDLE_COUNTER - 1; + irq_set <= 1'b1; // emit irq when command done + end + end + end + end + + // ------------------------ TYPE III ------------------------- + if(cmd_type_3) begin + if(!floppy_present) begin + // no image selected -> send irq immediately + busy <= 1'b0; + motor_timeout_index <= MOTOR_IDLE_COUNTER - 1; + irq_set <= 1'b1; // emit irq when command done + end else begin + // read address + if(cmd[7:4] == 4'b1100) begin + // we are busy until the next setor header passes under the head + if(fd_ready && fd_sector_hdr) + data_read_start_set <= 1'b1; + + if(data_read_done) begin + data_read_done_clr <= 1'b1; + busy <= 1'b0; + motor_timeout_index <= MOTOR_IDLE_COUNTER - 1; + irq_set <= 1'b1; // emit irq when command done + end + end + end + end + end + + // stop motor if there was no command for 10 index pulses + indexD <= fd_index; + if(indexD && !fd_index) begin + // led motor timeout run once fdc is not busy anymore + if(!busy) begin + if(motor_timeout_index != 0) + motor_timeout_index <= motor_timeout_index - 4'd1; + else + motor_on <= 1'b0; + end + + if(motor_spin_up_sequence != 0) + motor_spin_up_sequence <= motor_spin_up_sequence - 4'd1; + end + end +end + +// floppy delivers data at a floppy generated rate (usually 250kbit/s), so the start and stop +// signals need to be passed forth and back from cpu clock domain to floppy data clock domain +reg data_read_start_set; +reg data_read_start_clr; +reg data_read_start; +always @(posedge data_read_start_set or posedge data_read_start_clr) begin + if(data_read_start_clr) data_read_start <= 1'b0; + else data_read_start <= 1'b1; +end + +reg data_read_done_set; +reg data_read_done_clr; +reg data_read_done; +always @(posedge data_read_done_set or posedge data_read_done_clr) begin + if(data_read_done_clr) data_read_done <= 1'b0; + else data_read_done <= 1'b1; +end + +// ==================================== FIFO ================================== + +// 1 kB buffer used to receive a sector as fast as possible from from the io +// controller. The internal transfer afterwards then runs at 250000 Bit/s +reg [7:0] fifo [1024]; +reg [10:0] fifo_rptr; +reg [10:0] fifo_wptr; + +// -------------------- data write ----------------------- +always @(posedge clkcpu or posedge cmd_rx) begin + reg old_stb; + + if(cmd_rx) begin + fifo_wptr <= 0; + old_stb <= 0; + end else begin + old_stb <= dio_in_strobe; + if(dio_in_strobe && ~fifo_wptr[10]) begin + fifo[fifo_wptr] <= dio_in; + end + else + if(old_stb && ~dio_in_strobe) begin + if(~fifo_wptr[10]) fifo_wptr <= fifo_wptr + 1'd1; + end + end +end + +// -------------------- data read ----------------------- + +reg dclkD, dclkD2; +reg [10:0] data_read_cnt; +always @(posedge clkcpu) begin + reg inc = 0; + // reset fifo read pointer on reception of a new command + if(cmd_rx) + fifo_rptr <= 11'd0; + + data_read_start_clr <= 1'b0; + data_read_done_set <= 1'b0; + drq_set <= 1'b0; + + // received request to read data + if(data_read_start) begin + data_read_start_clr <= 1'b1; + + // read_address command has 6 data bytes + if(cmd[7:4] == 4'b1100) + data_read_cnt <= 11'd6+11'd1; + + // read sector has 1024 data bytes + if(cmd[7:5] == 3'b100) + data_read_cnt <= 11'd1024+11'd1; + end + + inc <= 0; + if(inc & ~fifo_rptr[10]) fifo_rptr <= fifo_rptr + 1'd1; + + // rising edge of floppy data clock (fd_dclk) + dclkD <= fd_dclk; + dclkD2 <= dclkD; + if(dclkD && !dclkD2) begin + if(data_read_cnt != 0) begin + if(data_read_cnt != 1) begin + drq_set <= 1'b1; + + // read_address + if(cmd[7:4] == 4'b1100) begin + case(data_read_cnt) + 7: data_out <= fd_track; + 6: data_out <= { 7'b0000000, floppy_side }; + 5: data_out <= fd_sector; + 4: data_out <= 8'd3; // TODO: sec size 0=128, 1=256, 2=512, 3=1024 + 3: data_out <= 8'ha5; + 2: data_out <= 8'h5a; + endcase // case (data_read_cnt) + end + + // read sector + if(cmd[7:5] == 3'b100) begin + if(~fifo_rptr[10]) begin + data_out <= fifo[fifo_rptr]; + inc <= 1; + end + end + end + + // count down and stop after last byte + data_read_cnt <= data_read_cnt - 11'd1; + if(data_read_cnt == 1) + data_read_done_set <= 1'b1; + end + end +end + +// the status byte +wire [7:0] status = { motor_on, + floppy_write_protected, // wrprot + cmd_type_1?motor_spin_up_done:1'b0, // data mark + !floppy_present, // record not found + 1'b0, // crc error + cmd_type_1?(fd_track == 0):1'b0, + cmd_type_1?~fd_index:floppy_drq, + busy } /* synthesis keep */; + +reg [7:0] track; +reg [7:0] sector; +reg [7:0] data_in; +reg [7:0] data_out; + +reg step_dir; +reg motor_on; + +// ---------------------------- command register ----------------------- +reg [7:0] cmd; +wire cmd_type_1 = (cmd[7] == 1'b0); +wire cmd_type_2 = (cmd[7:6] == 2'b10); +wire cmd_type_3 = (cmd[7:5] == 3'b111) || (cmd[7:4] == 4'b1100); +wire cmd_type_4 = (cmd[7:4] == 4'b1101); + +localparam FDC_REG_CMDSTATUS = 0; +localparam FDC_REG_TRACK = 1; +localparam FDC_REG_SECTOR = 2; +localparam FDC_REG_DATA = 3; + +// CPU register read +always @(wb_stb, wb_cyc, wb_adr, wb_we) begin + wb_dat_o = 8'h00; + + if(wb_stb && wb_cyc && !wb_we) begin + case(wb_adr[3:2]) + FDC_REG_CMDSTATUS: wb_dat_o = status; + FDC_REG_TRACK: wb_dat_o = track; + FDC_REG_SECTOR: wb_dat_o = sector; + FDC_REG_DATA: wb_dat_o = data_out; + endcase + end +end + +// cpu register write +reg cmd_rx; +reg cmd_rx_i; +reg last_stb; + +always @(posedge clkcpu) begin + if(!floppy_reset) begin + // clear internal registers + cmd <= 8'h00; + track <= 8'h00; + sector <= 8'h00; + + // reset state machines and counters + cmd_rx_i <= 1'b0; + cmd_rx <= 1'b0; + last_stb <= 1'b0; + end else begin + last_stb <= wb_stb; + + // cmd_rx is delayed to make sure all signals (the cmd!) are stable when + // cmd_rx is evaluated + cmd_rx <= cmd_rx_i; + + // command reception is ack'd by fdc going busy + if(busy) + cmd_rx_i <= 1'b0; + + // only react if stb just raised + if(!last_stb && wb_stb && wb_cyc && wb_we) begin + if(wb_adr[3:2] == FDC_REG_CMDSTATUS) begin // command register + cmd <= wb_dat_i; + cmd_rx_i <= 1'b1; + + // ------------- TYPE I commands ------------- + if(wb_dat_i[7:4] == 4'b0000) begin // RESTORE + step_to <= 8'd0; + track <= 8'd0; + end + + if(wb_dat_i[7:4] == 4'b0001) begin // SEEK + step_to <= data_in; + track <= data_in; + end + + if(wb_dat_i[7:5] == 3'b001) begin // STEP + step_to <= (step_dir == 1)?(track + 8'd1):(track - 8'd1); + if(wb_dat_i[4]) track <= (step_dir == 1)?(track + 8'd1):(track - 8'd1); + end + + if(wb_dat_i[7:5] == 3'b010) begin // STEP-IN + step_to <= track + 8'd1; + step_dir <= 1'b1; + if(wb_dat_i[4]) track <= track + 8'd1; + end + + if(wb_dat_i[7:5] == 3'b011) begin // STEP-OUT + step_to <= track - 8'd1; + step_dir <= 1'b0; + if(wb_dat_i[4]) track <= track - 8'd1; + end + + // ------------- TYPE II commands ------------- + if(wb_dat_i[7:5] == 3'b100) begin // read sector + end + + if(wb_dat_i[7:5] == 3'b101) begin // write sector + end + + // ------------- TYPE III commands ------------ + if(wb_dat_i[7:4] == 4'b1100) begin // read address + end + + if(wb_dat_i[7:4] == 4'b1110) begin // read track + end + + if(wb_dat_i[7:4] == 4'b1111) begin // write track + end + + // ------------- TYPE IV commands ------------- + if(wb_dat_i[7:4] == 4'b1101) begin // force intrerupt + end + end + + if(wb_adr[3:2] == FDC_REG_TRACK) // track register + track <= wb_dat_i; + + if(wb_adr[3:2] == FDC_REG_SECTOR) // sector register + sector <= wb_dat_i; + + if(wb_adr[3:2] == FDC_REG_DATA) // data register + data_in <= wb_dat_i; + end + end +end + +endmodule diff --git a/floppy.v b/floppy.v new file mode 100644 index 0000000..dc87f5b --- /dev/null +++ b/floppy.v @@ -0,0 +1,258 @@ +// +// floppy.v +// +// Copyright (c) 2015 Till Harbaum +// +// 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 floppy ( + // main clock + input clk, + input select, + input motor_on, + input step_in, + input step_out, + + output dclk, // data clock + output [6:0] track, // number of track under head + output [3:0] sector, // number of sector under head, 0 = no sector + output sector_hdr, // valid sector header under head + output sector_data, // valid sector data under head + + output ready, // drive is ready, data can be read + output reg index +); + +// The sysclock is the value all floppy timings are derived from. +// Default: 8 MHz +localparam SYS_CLK = 8000000; + +assign sector_hdr = (sec_state == SECTOR_STATE_HDR); +assign sector_data = (sec_state == SECTOR_STATE_DATA); + +// a standard DD floppy has a data rate of 250kBit/s and rotates at 300RPM +localparam RATE = 250000; +localparam RPM = 300; +localparam STEPBUSY = 18; // 18ms after step data can be read +localparam SPINUP = 500; // drive spins up in up to 800ms +localparam SPINDOWN = 300; // GUESSED: drive spins down in 300ms +localparam INDEX_PULSE_LEN = 5; // fd1036 data sheet says 1~8ms +localparam SECTOR_HDR_LEN = 6; // GUESSED: Sector header is 6 bytes +localparam TRACKS = 85; // max allowed track + +// Archimedes specific values +localparam SECTOR_LEN = 1024; // Default sector size is 1k on Archie ... +localparam SPT = 5; // ... with 5 sectors per track +localparam SECTOR_BASE = 0; // number of first sector on track (archie 0, dos 1) + +// number of physical bytes per track +localparam BPT = RATE*60/(8*RPM); + +// report disk ready if it spins at full speed and head is not moving +assign ready = select && (rate == RATE) && (step_busy == 0); + +// ================================================================ +// ========================= INDEX PULSE ========================== +// ================================================================ + +// Index pulse generation. Pulse starts with the begin of index_pulse_start +// and lasts INDEX_PULSE_CYCLES system clock cycles +localparam INDEX_PULSE_CYCLES = INDEX_PULSE_LEN * SYS_CLK / 1000; +reg [15:0] index_pulse_cnt; +always @(posedge clk) begin + if(index_pulse_start && (index_pulse_cnt == INDEX_PULSE_CYCLES-1)) begin + index <= 1'b0; + index_pulse_cnt <= 16'd0; + end else if(index_pulse_cnt == INDEX_PULSE_CYCLES-1) + index <= 1'b1; + else + index_pulse_cnt <= index_pulse_cnt + 16'd1; +end + +// ================================================================ +// ======================= track handling ========================= +// ================================================================ + +localparam STEP_BUSY_CLKS = (SYS_CLK/1000)*STEPBUSY; // steprate is in ms + +assign track = current_track; +reg [6:0] current_track = 7'd0; + +reg step_inD; +reg step_outD; +reg [17:0] step_busy; + +always @(posedge clk) begin + step_inD <= step_in; + step_outD <= step_out; + + if(step_busy != 0) + step_busy <= step_busy - 18'd1; + + if(select) begin + // rising edge of step signal starts step + if(step_in && !step_inD) begin + if(current_track != 0) current_track <= current_track - 7'd1; + step_busy <= STEP_BUSY_CLKS; + end + + if(step_out && !step_outD) begin + if(current_track != TRACKS-1) current_track <= current_track + 7'd1; + step_busy <= STEP_BUSY_CLKS; + end + end +end + +// ================================================================ +// ====================== sector handling ========================= +// ================================================================ + +// track has BPT bytes +// SPT sectors are stored on the track +localparam SECTOR_GAP_LEN = BPT/SPT - (SECTOR_LEN + SECTOR_HDR_LEN); + +assign sector = current_sector; + +localparam SECTOR_STATE_GAP = 2'd0; +localparam SECTOR_STATE_HDR = 2'd1; +localparam SECTOR_STATE_DATA = 2'd2; + +// we simulate an interleave of 1 +reg [3:0] start_sector = SECTOR_BASE; + +reg [1:0] sec_state; +reg [9:0] sec_byte_cnt; // counting bytes within sectors +reg [3:0] current_sector = SECTOR_BASE; + +always @(posedge byte_clk) begin + if(index_pulse_start) begin + sec_byte_cnt <= SECTOR_GAP_LEN-1; + sec_state <= SECTOR_STATE_GAP; // track starts with gap + current_sector <= start_sector; // track starts with sector 1 + end else begin + if(sec_byte_cnt == 0) begin + case(sec_state) + SECTOR_STATE_GAP: begin + sec_state <= SECTOR_STATE_HDR; + sec_byte_cnt <= SECTOR_HDR_LEN-1; + end + + SECTOR_STATE_HDR: begin + sec_state <= SECTOR_STATE_DATA; + sec_byte_cnt <= SECTOR_LEN-1; + end + + SECTOR_STATE_DATA: begin + sec_state <= SECTOR_STATE_GAP; + sec_byte_cnt <= SECTOR_GAP_LEN-1; + if(current_sector == SECTOR_BASE+SPT-1) + current_sector <= SECTOR_BASE; + else + current_sector <= sector + 4'd1; + end + + default: + sec_state <= SECTOR_STATE_GAP; + + endcase + end else + sec_byte_cnt <= sec_byte_cnt - 10'd1; + end +end + +// ================================================================ +// ========================= BYTE CLOCK =========================== +// ================================================================ + +// An ed floppy at 300rpm with 1MBit/s has max 31.250 bytes/track +// thus we need to support up to 31250 events +reg [14:0] byte_cnt; +reg index_pulse_start; +always @(posedge byte_clk) begin + index_pulse_start <= 1'b0; + + if(byte_cnt == BPT-1) begin + byte_cnt <= 0; + index_pulse_start <= 1'b1; + end else + byte_cnt <= byte_cnt + 1; +end + +// Make byte clock from bit clock. +// When a DD disk spins at 300RPM every 32us a byte passes the disk head +assign dclk = byte_clk; +wire byte_clk = clk_cnt2[2]; +reg [2:0] clk_cnt2; +always @(posedge data_clk) + clk_cnt2 <= clk_cnt2 + 1; + +// ================================================================ +// ===================== SPIN VIRTUAL DISK ======================== +// ================================================================ + +// number of system clock cycles after which disk has reached +// full speed +localparam SPIN_UP_CLKS = SYS_CLK/1000*SPINUP; +localparam SPIN_DOWN_CLKS = SYS_CLK/1000*SPINDOWN; +reg [31:0] spin_up_counter; + +// internal motor on signal that is only true if the drive is selected +wire motor_on_sel = motor_on && select; + +// data rate determines rotation speed +reg [31:0] rate = 0; +reg motor_onD; + +always @(posedge clk) begin + motor_onD <= motor_on_sel; + + // reset spin_up counter whenever motor state changes + if(motor_onD != motor_on_sel) + spin_up_counter <= 32'd0; + else begin + spin_up_counter <= spin_up_counter + RATE; + + if(motor_on_sel) begin + // spinning up + if(spin_up_counter > SPIN_UP_CLKS) begin + if(rate < RATE) + rate <= rate + 32'd1; + spin_up_counter <= spin_up_counter - (SPIN_UP_CLKS - RATE); + end + end else begin + // spinning down + if(spin_up_counter > SPIN_DOWN_CLKS) begin + if(rate > 0) + rate <= rate - 32'd1; + spin_up_counter <= spin_up_counter - (SPIN_DOWN_CLKS - RATE); + end + end // else: !if(motor_on) + end // else: !if(motor_onD != motor_on) +end + +// Generate a data clock from the system clock. This depends on motor +// speed and reaches the full rate when the disk rotates at 300RPM. No +// valid data can be read until the disk has reached it's full speed. +reg data_clk; +reg [31:0] clk_cnt; +always @(posedge clk) begin + if(clk_cnt + rate > SYS_CLK/2) begin + clk_cnt <= clk_cnt - (SYS_CLK/2 - rate); + data_clk <= !data_clk; + end else + clk_cnt <= clk_cnt + rate; +end + +endmodule diff --git a/i2cSlave.v b/i2cSlave.v new file mode 100644 index 0000000..416b599 --- /dev/null +++ b/i2cSlave.v @@ -0,0 +1,181 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// i2cSlave.v //// +//// //// +//// This file is part of the i2cSlave opencores effort. +//// //// +//// //// +//// Module Description: //// +//// You will need to modify this file to implement your +//// interface. +//// //// +//// To Do: //// +//// +//// //// +//// Author(s): //// +//// - Steve Fielding, sfielding@base2designs.com //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2008 Steve Fielding and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from //// +//// //// +////////////////////////////////////////////////////////////////////// +// +`include "i2cSlave_define.v" + + +module i2cSlave ( + clk, + rst, + sdaIn, + sdaOut, + scl +); + +input clk; +input rst; +input sdaIn; +output sdaOut; +input scl; + +// local wires and regs +reg sdaDeb; +reg sclDeb; +reg [`DEB_I2C_LEN-1:0] sdaPipe; +reg [`DEB_I2C_LEN-1:0] sclPipe; + +reg [`SCL_DEL_LEN-1:0] sclDelayed; +reg [`SDA_DEL_LEN-1:0] sdaDelayed; +reg [1:0] startStopDetState; +wire clearStartStopDet; + + +wire [7:0] regAddr; +wire [7:0] dataToRegIF; +wire writeEn; +wire [7:0] dataFromRegIF; +reg [1:0] rstPipe; +wire rstSyncToClk; +reg startEdgeDet; + +// sync rst rsing edge to clk +always @(posedge clk) begin + if (rst == 1'b1) + rstPipe <= 2'b11; + else + rstPipe <= {rstPipe[0], 1'b0}; +end + +assign rstSyncToClk = rstPipe[1]; + +// debounce sda and scl +always @(posedge clk) begin + if (rstSyncToClk == 1'b1) begin + sdaPipe <= {`DEB_I2C_LEN{1'b1}}; + sdaDeb <= 1'b1; + sclPipe <= {`DEB_I2C_LEN{1'b1}}; + sclDeb <= 1'b1; + end + else begin + sdaPipe <= {sdaPipe[`DEB_I2C_LEN-2:0], sdaIn}; + sclPipe <= {sclPipe[`DEB_I2C_LEN-2:0], scl}; + if (&sclPipe[`DEB_I2C_LEN-1:1] == 1'b1) + sclDeb <= 1'b1; + else if (|sclPipe[`DEB_I2C_LEN-1:1] == 1'b0) + sclDeb <= 1'b0; + if (&sdaPipe[`DEB_I2C_LEN-1:1] == 1'b1) + sdaDeb <= 1'b1; + else if (|sdaPipe[`DEB_I2C_LEN-1:1] == 1'b0) + sdaDeb <= 1'b0; + end +end + + +// delay scl and sda +// sclDelayed is used as a delayed sampling clock +// sdaDelayed is only used for start stop detection +// Because sda hold time from scl falling is 0nS +// sda must be delayed with respect to scl to avoid incorrect +// detection of start/stop at scl falling edge. +always @(posedge clk) begin + if (rstSyncToClk == 1'b1) begin + sclDelayed <= {`SCL_DEL_LEN{1'b1}}; + sdaDelayed <= {`SDA_DEL_LEN{1'b1}}; + end + else begin + sclDelayed <= {sclDelayed[`SCL_DEL_LEN-2:0], sclDeb}; + sdaDelayed <= {sdaDelayed[`SDA_DEL_LEN-2:0], sdaDeb}; + end +end + +// start stop detection +always @(posedge clk) begin + if (rstSyncToClk == 1'b1) begin + startStopDetState <= `NULL_DET; + startEdgeDet <= 1'b0; + end + else begin + if (sclDeb == 1'b1 && sdaDelayed[`SDA_DEL_LEN-2] == 1'b0 && sdaDelayed[`SDA_DEL_LEN-1] == 1'b1) + startEdgeDet <= 1'b1; + else + startEdgeDet <= 1'b0; + if (clearStartStopDet == 1'b1) + startStopDetState <= `NULL_DET; + else if (sclDeb == 1'b1) begin + if (sdaDelayed[`SDA_DEL_LEN-2] == 1'b1 && sdaDelayed[`SDA_DEL_LEN-1] == 1'b0) + startStopDetState <= `STOP_DET; + else if (sdaDelayed[`SDA_DEL_LEN-2] == 1'b0 && sdaDelayed[`SDA_DEL_LEN-1] == 1'b1) + startStopDetState <= `START_DET; + end + end +end + + +registerInterface u_registerInterface( + .clk(clk), + .addr(regAddr), + .dataIn(dataToRegIF), + .writeEn(writeEn), + .dataOut(dataFromRegIF) +); + +serialInterface u_serialInterface ( + .clk(clk), + .rst(rstSyncToClk | startEdgeDet), + .dataIn(dataFromRegIF), + .dataOut(dataToRegIF), + .writeEn(writeEn), + .regAddr(regAddr), + .scl(sclDelayed[`SCL_DEL_LEN-1]), + .sdaIn(sdaDeb), + .sdaOut(sdaOut), + .startStopDetState(startStopDetState), + .clearStartStopDet(clearStartStopDet) +); + + +endmodule + + + diff --git a/i2cSlaveTop.v b/i2cSlaveTop.v new file mode 100644 index 0000000..124b26a --- /dev/null +++ b/i2cSlaveTop.v @@ -0,0 +1,74 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// i2cSlaveTop.v //// +//// //// +//// This file is part of the i2cSlave opencores effort. +//// //// +//// //// +//// Module Description: //// +//// You will need to modify this file to implement your +//// interface. +//// //// +//// To Do: //// +//// +//// //// +//// Author(s): //// +//// - Steve Fielding, sfielding@base2designs.com //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2008 Steve Fielding and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from //// +//// //// +////////////////////////////////////////////////////////////////////// +// +`include "i2cSlave_define.v" + + +module i2cSlaveTop ( + clk, + rst, + sdaIn, + sdaOut, + scl +); +input clk; +input rst; +input sdaIn; +output sdaOut; +input scl; + + +i2cSlave u_i2cSlave( + .clk(clk), + .rst(rst), + .sdaIn(sdaIn), + .sdaOut(sdaOut), + .scl(scl) +); + + +endmodule + + + diff --git a/i2cSlave_define.v b/i2cSlave_define.v new file mode 100644 index 0000000..2b1384a --- /dev/null +++ b/i2cSlave_define.v @@ -0,0 +1,68 @@ +// ----------------------- i2cSlave_define.v -------------------- + +// stream states +`define STREAM_IDLE 2'b00 +`define STREAM_READ 2'b01 +`define STREAM_WRITE_ADDR 2'b10 +`define STREAM_WRITE_DATA 2'b11 + +// start stop detection states +`define NULL_DET 2'b00 +`define START_DET 2'b01 +`define STOP_DET 2'b10 + +// i2c ack and nak +`define I2C_NAK 1'b1 +`define I2C_ACK 1'b0 + +// ---------------------------------------------------------------- +// ------------- modify constants below this line ----------------- +// ---------------------------------------------------------------- + +// i2c device address +`define I2C_ADDRESS 7'h50 + +// System clock frequency in MHz +// If you are using a clock frequency below 24MHz, then the macro +// for SDA_DEL_LEN will result in compile errors for i2cSlave.v +// you will need to hand tweak the SDA_DEL_LEN constant definition +`define CLK_FREQ 32 + +// Debounce SCL and SDA over this many clock ticks +// The rise time of SCL and SDA can be up to 1000nS (in standard mode) +// so it is essential to debounce the inputs. +// The spec requires 0.05V of hysteresis, but in practise +// simply debouncing the inputs is sufficient +// I2C spec requires suppresion of spikes of +// maximum duration 50nS, so this debounce time should be greater than 50nS +// Also increases data hold time and decreases data setup time +// during an I2C read operation +// 10 ticks = 208nS @ 48MHz +`define DEB_I2C_LEN (10*`CLK_FREQ)/48 + +// Delay SCL for use as internal sampling clock +// Using delayed version of SCL to ensure that +// SDA is stable when it is sampled. +// Not entirely citical, as according to I2C spec +// SDA should have a minimum of 100nS of set up time +// with respect to SCL rising edge. But with the very slow edge +// speeds used in I2C it is better to err on the side of caution. +// This delay also has the effect of adding extra hold time to the data +// with respect to SCL falling edge. I2C spec requires 0nS of data hold time. +// 10 ticks = 208nS @ 48MHz +`define SCL_DEL_LEN (10*`CLK_FREQ)/48 + +// Delay SDA for use in start/stop detection +// Use delayed SDA during start/stop detection to avoid +// incorrect detection at SCL falling edge. +// From I2C spec start/stop setup is 600nS with respect to SCL rising edge +// and start/stop hold is 600nS wrt SCL falling edge. +// So it is relatively easy to discriminate start/stop, +// but data setup time is a minimum of 100nS with respect to SCL rising edge +// and 0nS hold wrt to SCL falling edge. +// So the tricky part is providing robust start/stop detection +// in the presence of regular data transitions. +// This delay time should be less than 100nS +// 4 ticks = 83nS @ 48MHz +`define SDA_DEL_LEN (4*`CLK_FREQ)/48 + diff --git a/ioc.v b/ioc.v new file mode 100644 index 0000000..d80bfb2 --- /dev/null +++ b/ioc.v @@ -0,0 +1,316 @@ +`timescale 1ns / 1ps +/* ioc.v + + Copyright (c) 2012-2015, Stephen J. Leary + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the nor the + * names of its contributors may be used to endorse or promote products + * derived from this software 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 BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +module ioc( + + input clkcpu, // cpu bus clock domain + output clk2m_en, + output clk8m_en, + + input por, // power on reset signal. + + input [5:0] c_in, + output[5:0] c_out, + + output [7:1] select, // perhiperhal select lines + output sext, // external perhiperhal select + + input [1:0] fh, // fast high interrupt. + input [7:0] il, // active low interrupt lines + input ir, // + + // "wishbone" bus + input wb_we, + input wb_stb, + input wb_cyc, + + input [6:2] wb_adr, + input [7:0] wb_dat_i, + output [7:0] wb_dat_o, + + // perhaps rename but its part of an IOC bus cycle. + input [2:0] wb_bank, + + // interrupts + output irq, + output firq, + + // keyboard interface to arm controller. Data is valid + // in rising edge of strobe + output reg [7:0] kbd_out_data, + output reg kbd_out_strobe, + input [7:0] kbd_in_data, + input kbd_in_strobe +); + +reg [3:0] clk2m_count; +reg [1:0] clk8m_count; + +wire [7:0] irqa_dout, irqb_dout, firq_dout; +wire irqa_req, irqb_req, firq_req; +wire irqa_selected, irqb_selected, firq_selected; + +wire ctrl_selected = wb_adr[6:2] == 5'd0 /* synthesis keep */; +wire [7:0] ctrl_dout; +reg [5:0] ctrl_state; + +wire serial_selected = wb_adr[6:2] == 5'd1 /* synthesis keep */; + +wire write_request = (wb_bank == 3'b000) & wb_stb & wb_cyc & wb_we; +wire read_request = (wb_bank == 3'b000) & wb_stb & wb_cyc & !wb_we; + +// input data irq is cleared when cpu reads input port +reg kbd_in_irq_ack; +reg kbd_in_irq = 0; + +// keyboard input is valid on kbd_in_strobe. Latch data then +// and set irq +reg [7:0] kbd_in_data_latch; + +always @(posedge clkcpu) begin + reg old_ack; + + old_ack <= kbd_in_irq_ack; + if(kbd_in_strobe) begin + kbd_in_data_latch <= kbd_in_data; + kbd_in_irq <= 1; + end else if(~old_ack & kbd_in_irq_ack) begin + kbd_in_irq <= 0; + end +end + +// faked kbd tx timing +reg[4:0] txcount = 5'd0; +wire txdone = txcount == 5'd0 /* synthesis keep */; + +// edge detect for IR +reg ir_r; +wire ir_edge; + + // Instantiate the Unit Under Test (UUT) + ioc_irq #( + .ADDRESS(2'b01), + .PERMBITS(8'h80), + .CANCLEAR(8'b01111111) + ) IRQA + ( + .clkcpu ( clkcpu ), + + .i ( {1'b1, timer[1].reload, timer[0].reload, por, ir_edge, 3'b000}), + .irq ( irqa_req ), + .c ( 8'h00 ), + .addr ( wb_adr[6:2] ), + .din ( wb_dat_i ), + .dout ( irqa_dout ), + .sel ( irqa_selected ), + .write ( write_request ) + + ); + + // Instantiate the Unit Under Test (UUT) + ioc_irq #( + .ADDRESS(2'b10), + .CANCLEAR(8'b00000000) + ) IRQB + ( + .clkcpu ( clkcpu ), + + .i ( { kbd_in_irq, txdone, ~il[5:0]}), + .c ( {!kbd_in_irq, ~txdone, il[5:0]}), + .irq ( irqb_req ), + + .addr ( wb_adr[6:2] ), + .din ( wb_dat_i ), + .dout ( irqb_dout ), + .sel ( irqb_selected ), + .write ( write_request ) + ); + + + ioc_irq #( + .ADDRESS(2'b11), + .CANCLEAR(8'd0) + ) FIRQ + ( + .clkcpu ( clkcpu ), + + .i ( {6'h00, fh[1:0]} ), + .c ( {6'h00, ~fh[1:0]}), + .irq ( firq_req ), + + .addr ( wb_adr[6:2] ), + .din ( wb_dat_i ), + .dout ( firq_dout ), + .sel ( firq_selected ), + + .write ( write_request ) + ); + + +localparam TIMERS = 4; + +genvar c; +generate + + for (c = 0; c < TIMERS; c = c + 1) begin: timer + + reg[15:0] latch_i; + reg[15:0] counter; + reg[15:0] latch_o; + reg reload; + + wire selected = wb_adr[6] & (c[1:0] == wb_adr[5:4]); + wire [7:0] out = wb_adr[2] ? latch_o[15:8] : latch_o[7:0]; + + initial begin + + latch_i = 16'd0; + counter = 16'd0; + latch_o = 16'd0; + reload = 1'b0; + + end + + always @(posedge clkcpu) begin + + reload <= 1'b0; + + if (write_request & selected) begin + + case (wb_adr[3:2]) + + 2'b00: latch_i[7:0] <= wb_dat_i; + 2'b01: latch_i[15:8] <= wb_dat_i; + 2'b10: counter <= {latch_i[15:4],4'd0}; + 2'b11: latch_o <= counter; + + endcase + + end else if (clk2m_en) begin + + counter <= counter - 15'd1; + + if (~|counter) begin + + reload <= 1'b1; + counter <= {latch_i[15:4],4'd0}; + + end + + end + + end + + end + +endgenerate + +initial begin + + ctrl_state = 6'h3F; + + clk8m_count = 'd0; + clk2m_count = 'd0; + + ir_r = 1'b1; + +end + + + +// here we generate the ack signal and the 2mhz enable. +always @(posedge clkcpu) begin + + // generate strobe one clock cycle after data has been latched + kbd_out_strobe <= !txdone; + kbd_in_irq_ack <= serial_selected && read_request; + + ir_r <= ir; + + if (!txdone &&(timer[3].reload)) begin + + txcount <= txcount - 4'd1; + + end + + // increment the clock counters. + clk2m_count <= clk2m_count + 1'd1; + clk8m_count <= clk8m_count + 1'd1; + + if (write_request & ctrl_selected) begin + + ctrl_state <= wb_dat_i[5:0]; + + end + + if (write_request & serial_selected) begin + // simulate a serial port write to the console. + kbd_out_strobe <= 1'b0; + kbd_out_data <= wb_dat_i[7:0]; + txcount <= 5'd20; + end + + +end + +// external perhiperhal stuff. +assign {select, sext} = wb_bank == 3'b001 ? 8'b00000011 : + wb_bank == 3'b010 ? 8'b00000101 : + wb_bank == 3'b011 ? 8'b00001001 : + wb_bank == 3'b100 ? 8'b00010001 : + wb_bank == 3'b101 ? 8'b00100001 : + wb_bank == 3'b110 ? 8'b01000001 : + wb_bank == 3'b111 ? 8'b10000001 : 8'd0; + + +assign c_out = ctrl_state; +assign ctrl_dout = { ir, 1'b1, c_in & c_out }; + +assign ir_edge = ~ir_r & ir; + +// pulse the 2mhz & 8mhz clock enable line high when all the bits are set. +assign clk2m_en = &clk2m_count; +assign clk8m_en = &clk8m_count; + +assign wb_dat_o = read_request ? + (ctrl_selected ? ctrl_dout : + serial_selected ? kbd_in_data_latch : + irqa_selected ? irqa_dout : + irqb_selected ? irqb_dout : + firq_selected ? firq_dout : + timer[0].selected ? timer[0].out : + timer[1].selected ? timer[1].out : + timer[2].selected ? timer[2].out : + timer[3].selected ? timer[3].out : 8'hFF) : 8'hFF; + +assign irq = irqa_req | irqb_req; +assign firq = firq_req; +// sext is high if any bits of select are high + +endmodule diff --git a/ioc_irq.v b/ioc_irq.v new file mode 100644 index 0000000..6a1246f --- /dev/null +++ b/ioc_irq.v @@ -0,0 +1,80 @@ +`timescale 1ns / 1ps +/* ioc_irq.v + + Copyright (c) 2012-2014, Stephen J. Leary + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the nor the + * names of its contributors may be used to endorse or promote products + * derived from this software 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 BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + module ioc_irq #( + parameter ADDRESS=2'b01, + parameter CANCLEAR=8'b1111_1111, + parameter PERMBITS=8'h00) + ( + + input clkcpu, // cpu bus clock domain + + input [7:0] i, + input [7:0] c, + output irq, + + // cpu interface + input write, + + input [6:2] addr, + input [7:0] din, + output [7:0] dout, + output sel +); + +reg [7:0] mask = 8'h00; +reg [7:0] status = 8'h00; + +wire selected = ~addr[6] & (addr[5:4] == ADDRESS); + +always @(posedge clkcpu) begin + + status <= status & CANCLEAR | status & ~CANCLEAR & ~c | i | PERMBITS; + + if (selected & write) begin + + if (addr[3:2] == 2'b10) mask <= din; + + if (addr[3:2] == 2'b01) begin + status <= (status & ~CANCLEAR) | (status & ~din & CANCLEAR) | PERMBITS; + end + + end + +end + +assign sel = selected; + +assign irq = | (mask & status); + +assign dout = addr[3:2] == 2'b00 ? status : + addr[3:2] == 2'b01 ? mask & status : + addr[3:2] == 2'b10 ? mask : 8'd0; + +endmodule \ No newline at end of file diff --git a/jtag.cdf b/jtag.cdf new file mode 100644 index 0000000..915e98d --- /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("Archie.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..e62da40 --- /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("Archie-lite.sof") MfrSpec(OpMask(1)); + +ChainEnd; + +AlteraBegin; + ChainType(JTAG); +AlteraEnd; diff --git a/latches.v b/latches.v new file mode 100644 index 0000000..0af9125 --- /dev/null +++ b/latches.v @@ -0,0 +1,107 @@ +`timescale 1ns / 1ps +/* latches.v + + Copyright (c) 2015, Stephen J. Leary + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the nor the + * names of its contributors may be used to endorse or promote products + * derived from this software 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 BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +module latches( + + input clkcpu, // system cpu clock. + + // "wishbone bus" the ack is externally generated currently. + input wb_cyc, + input wb_stb, + input wb_we, + + input [15:2] wb_adr, // la + input [7:0] wb_dat_i, // bd + output [7:0] wb_dat_o, // bd + + // floppy latch signals. + output [3:0] floppy_drive, + output floppy_side, + output floppy_motor, + output floppy_inuse, + output floppy_density, + output floppy_reset, + + // place any signals that need to be passed up to the top after here. + + input [4:0] joy0, + input [4:0] joy1, + + output [1:0] baseclk, + output [1:0] syncpol + +); + +reg [7:0] printer_data; +reg [7:0] ext_latch_a; +reg [7:0] ext_latch_b; +reg [7:0] ext_latch_c; + +wire write_request = wb_stb & wb_cyc & wb_we; + +initial begin + + printer_data = 8'd0; + ext_latch_a = 8'hFF; + ext_latch_b = 8'hFF; + ext_latch_c = 8'd0; // A540 only. Used for VIDC enhancer. + +end + +always @(posedge clkcpu) begin + + if (write_request) begin + + case (wb_adr) + + 14'h0004: printer_data<= wb_dat_i; // 0x10 + 14'h0010: ext_latch_a <= wb_dat_i; // 0x40 + 14'h0006: ext_latch_b <= wb_dat_i; // 0x18 + 14'h0012: ext_latch_c <= wb_dat_i; // 0x48 + + endcase + + end + +end + +assign floppy_drive = ext_latch_a[3:0]; +assign floppy_side = ext_latch_a[4]; +assign floppy_motor = ext_latch_a[5]; +assign floppy_inuse = ext_latch_a[6]; +assign floppy_density = ext_latch_b[1]; +assign floppy_reset = ext_latch_b[3]; + +assign wb_dat_o = wb_adr == 14'h001e ? {3'b011, joy0} : + wb_adr == 14'h001f ? {3'b011, joy1} : 32'hFFFFFFFF; + +assign baseclk = ext_latch_c[1:0]; +assign syncpol = ext_latch_c[3:2]; + +endmodule diff --git a/memc.v b/memc.v new file mode 100644 index 0000000..b713c2d --- /dev/null +++ b/memc.v @@ -0,0 +1,433 @@ +`timescale 1ns / 1ps +/* memc.v + + Copyright (c) 2012-2014, Stephen J. Leary + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the nor the + * names of its contributors may be used to endorse or promote products + * derived from this software 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 BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +module memc( + + input clkcpu, + input rst_i, + + // cpu bus. + input cpu_we, + input cpu_stb, + input cpu_cyc, + output cpu_err, + output cpu_ack, + + input [25:0] cpu_address, + input [3:0] cpu_sel, + + // external memory bus. + output [23:2] mem_addr_o, + output mem_stb_o, + output mem_cyc_o, + output mem_we_o, + output [3:0] mem_sel_o, + + input mem_ack_i, + output [2:0] mem_cti_o, // burst / normal + + // supervisor mode + + input spvmd, + + // vidc interface + input flybk, + input hsync, + + input sndrq, + output sndak, + + input vidrq, + output vidak, + output vidw, // write to the video registers. + + // ioc interface + output ioc_cs, + output rom_low_cs, + output ram_cs, // accessing ram. + + // interrupts + + output sirq_n + +); + + parameter INITIAL_CURSOR_BASE = 19'h0_0000; + parameter INITIAL_SCREEN_BASE = 19'h0_0000; + parameter INITIAL_SCREEN_SIZE = 19'h4_b000; + + reg rom_overlay; + + reg [18:0] cur_address; // actual + reg [18:0] cur_init; + + reg [18:0] vid_address; // actual + reg [18:0] vid_init; + reg [18:0] vid_start; + reg [18:0] vid_end; + + reg [18:0] snd_sptr; // actual/current + reg [18:0] snd_endc; + + reg snd_next_valid; + reg [18:0] snd_start; + reg [18:0] snd_endn; + + reg [13:0] memc_control = 14'd0; + reg cur_load; + reg vid_load; + reg snd_load; + reg cpu_load; + + reg [3:0] dma_ack_r; + + wire dma_in_progress = cur_load | vid_load | snd_load; + wire dma_request = ~flybk & vidrq | memc_control[11] & sndrq; + reg dma_request_r; + wire video_dma_ip = cur_load | vid_load; + wire sound_dma_ip = snd_load; + + wire address_valid; + wire cpu_ram_cycle; + + wire phycs, tablew, romcs, memcw; + +// register addresses. +localparam REG_Vinit = 3'b000; +localparam REG_Vstart = 3'b001; +localparam REG_Vend = 3'b010; +localparam REG_Cinit = 3'b011; +localparam REG_Sstart = 3'b100; +localparam REG_SendN = 3'b101; +localparam REG_Sptr = 3'b110; +localparam REG_Ctrl = 3'b111; + +wire[25:0] phys_address; +wire table_valid; + +memc_translator PAGETABLES( + + .clkcpu ( clkcpu ), + .wr ( tablew ), + .spvmd ( spvmd ), + .page_size ( memc_control[3:2] ), + .osmd ( memc_control[12] ), + .mem_write ( cpu_we ), + .addr_i ( cpu_address ), + .addr_o ( phys_address ), + .valid ( table_valid ) +); + +initial begin + + // start with rom overlay + rom_overlay = 1'b1; + + // memc state registers + vid_load = 1'b0; + snd_load = 1'b0; + cur_load = 1'b0; + cpu_load = 1'b0; + + // sound init. + snd_next_valid = 1'b0; + dma_request_r = 1'b0; + // video init. + dma_ack_r = 4'd0; + + // initial cursor and video addresses + vid_init = INITIAL_SCREEN_BASE; + cur_init = INITIAL_CURSOR_BASE; + + vid_start = INITIAL_SCREEN_BASE; + vid_end = INITIAL_SCREEN_BASE + INITIAL_SCREEN_SIZE; + +end + +always @(posedge clkcpu) begin + + if (rst_i == 1'b1) begin + + vid_init <= INITIAL_SCREEN_BASE; + cur_init <= INITIAL_CURSOR_BASE; + vid_start <= INITIAL_SCREEN_BASE; + vid_end <= INITIAL_SCREEN_BASE + INITIAL_SCREEN_SIZE; + vid_address <= INITIAL_SCREEN_BASE; + cur_address <= INITIAL_CURSOR_BASE; + + cpu_load <= 1'b0; + rom_overlay <= 1'b1; + + memc_control[11] <= 1'b0; // disable sound dma on reset. + + dma_request_r <= 1'b0; + + end else begin + + + dma_request_r <= dma_request; + + // cpu cycle. + if (cpu_cyc & cpu_stb) begin + + // logic to ensure that the rom overlay gets deactivated. + if (cpu_address[25:24] == 2'b11) begin + + rom_overlay <= 1'b0; + + end + + // ensure no video cycle is active or about to start. + if (~dma_request_r & ~dma_in_progress) begin + + cpu_load <= 1'b1; + + end + + // prevent the cpu hogging the bus. + if (cpu_load & dma_request_r & (cpu_ack | cpu_err)) begin + + cpu_load <= 1'b0; + + end + + if (memw) begin + + // load the registers. + // all the registers are loaded here. + case (cpu_address[19:17]) + + REG_Vinit: vid_init <= {cpu_address[16:2], 4'b0000}; + REG_Vstart: vid_start <= {cpu_address[16:2], 4'b0000}; + REG_Vend: vid_end <= {cpu_address[16:2], 4'b0000}; + REG_Cinit: cur_init <= {cpu_address[16:2], 4'b0000}; + + REG_Sstart: begin + + $display("Sstart: %x", {cpu_address[16:2], 4'b0000}); + snd_next_valid <= 1'b1; + snd_start <= {cpu_address[16:2], 4'b0000}; + + end + + REG_SendN: begin + + $display("SendN: %x", {cpu_address[16:2], 4'b0000}); + snd_endn <= {cpu_address[16:2], 4'b0000}; + + end + + REG_Sptr: begin + + $display("Sound buffer swap"); + snd_sptr <= snd_start; + + if (snd_next_valid == 1'b1) begin + snd_endc <= snd_endn; + snd_next_valid <= 1'b0; + end + + end + + REG_Ctrl: begin + + $display("MEMC Control Register: %x", cpu_address[13:0]); + memc_control <= cpu_address[13:0]; + + end + + endcase + + end + + end else begin + + cpu_load <= 1'b0; + + end + + // video dma stuff. + if (flybk == 1'b1) begin + + // stop all video dma on flybk + vid_address <= vid_init; + cur_address <= cur_init; + + if (vid_load | cur_load) begin + + dma_ack_r <= 4'd0; + + end + + vid_load <= 1'b0; + cur_load <= 1'b0; + + end + + // do the dma count for all cycle types. + if (dma_in_progress & mem_ack_i) begin + + dma_ack_r <= dma_ack_r + 3'd1; + + if (dma_ack_r == 4'd3) begin + + vid_load <= 1'b0; + snd_load <= 1'b0; + cur_load <= 1'b0; + dma_ack_r <= 4'd0; + + end + + end + + if (dma_request_r === 1'b1) begin + + // priority is to video over sound. + if (vidrq & ~dma_in_progress & ~cpu_load) begin + + if (hsync == 1'b1) begin + + vid_load <= 1'b1; + + end else begin + + cur_load <= 1'b1; + + end + + end else if (sndrq & ~dma_in_progress & ~cpu_load) begin + + snd_load <= 1'b1; + + end + + end + + if (video_dma_ip) begin + + if ((vidak & vid_load) == 1'b1) begin + + // advance the pointer to the next location. + vid_address <= vid_address + 19'd4; + + end else if ((vidak & cur_load) == 1'b1) begin + + // advance the cursor pointer to the next location. + cur_address <= cur_address + 19'd4; + + end + + end else begin + + // cant wrap during a burst + if (vid_address > vid_end) begin + + // loop back to vid_start when we reach the end. + vid_address <= vid_start; + + end + + end + + if (sound_dma_ip) begin + + if ((sndak & snd_load) == 1'b1) begin + + // advance the pointer to the next location. + snd_sptr <= snd_sptr + 19'd4; + end + + end else begin + + // cant wrap during a burst + if (snd_sptr > snd_endc) begin + + snd_sptr <= snd_start; + + if (snd_next_valid == 1'b1) begin + snd_endc <= snd_endn; + snd_next_valid <= 1'b0; + end + + end + + end + + end + +end + +wire [21:2] ram_page = memc_control[3:2] == 2'b00 ? {3'd0, cpu_address[18:2]}: + memc_control[3:2] == 2'b01 ? {2'd0, cpu_address[19:2]} : + memc_control[3:2] == 2'b10 ? {1'd0, cpu_address[20:2]} : cpu_address[21:2]; + +assign mem_addr_o = vid_load ? {5'd0, vid_address[18:2]} : + cur_load ? {5'd0, cur_address[18:2]} : + snd_load ? {5'd0, snd_sptr[18:2]} : + phycs ? {2'd0, ram_page} : // use physical memory + romcs ? {3'b010, cpu_address[20:2]} : // use 2mb and up for rom space. + table_valid & logcs ? phys_address[23:2] : 22'd0; // use logical memory. + + +// does this cpu cycle need to go to external RAM/ROM? +assign cpu_ram_cycle = cpu_cyc & cpu_stb & (table_valid | phycs | romcs); + +assign mem_cyc_o = cpu_load ? cpu_cyc : dma_in_progress; +assign mem_stb_o = cpu_load ? cpu_stb : dma_in_progress; +assign mem_sel_o = cpu_load ? cpu_sel : 4'b1111; +assign mem_we_o = cpu_load ? cpu_we & (phycs & spvmd | table_valid & logcs) & ~romcs : 1'b0; +assign mem_cti_o = cpu_load ? 3'b000 : 3'b010; + +assign address_valid = (logcs & table_valid) | rom_low_cs| ioc_cs | memw | tablew | vidc_cs | (phycs & ~cpu_we) | (phycs & spvmd & cpu_we) | romcs; +wire err = ~address_valid; + +assign cpu_ack = cpu_load ? mem_ack_i & ~err : 1'b0; +assign cpu_err = cpu_load ? mem_ack_i & err : 1'b0; + +assign tablew = cpu_load & cpu_cyc & cpu_we & spvmd & (cpu_address[25:23] == 3'b111) & (cpu_address[12] == 0) & (cpu_address[7] == 0); // &3800000+ +wire memw = cpu_load & cpu_cyc & cpu_we & spvmd & (cpu_address[25:21] == 5'b11011); // &3600000 +assign vidw = cpu_load & cpu_cyc & cpu_we & vidc_cs; // &3400000 + +// bus chip selects +wire logcs = cpu_address[25] == 1'b0; // 0000000-&1FFFFFF +assign phycs = cpu_address[25:24] == 2'b10; //&2000000 - &2FFFFFF +assign ioc_cs = spvmd & (cpu_address[25:22] == 4'b1100); //&3000000 - &33FFFFF +wire vidc_cs = spvmd & (cpu_address[25:21] == 5'b11010); // &3400000 - &35FFFFF (WE & SPVMD) +assign rom_low_cs = (cpu_address[25:22] == 4'b1101); + +assign romcs = ((cpu_address[25:23] == 3'b111) | (cpu_address[25:19] == 7'h00) & rom_overlay); + +assign vidak = cpu_load ? 1'b0 : video_dma_ip & mem_ack_i; +assign sndak = cpu_load ? 1'b0 : sound_dma_ip & mem_ack_i; + +assign sirq_n = snd_next_valid; +assign ram_cs = table_valid | phycs | romcs; + +wire mem_virtual= table_valid & ~cpu_address[25]; + +endmodule diff --git a/memc_translator.v b/memc_translator.v new file mode 100644 index 0000000..9b00c76 --- /dev/null +++ b/memc_translator.v @@ -0,0 +1,243 @@ +`timescale 1ns / 1ps +/* memc_translator.v + + Copyright (c) 2012-2014, Stephen J. Leary + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the nor the + * names of its contributors may be used to endorse or promote products + * derived from this software 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 BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +module memc_translator +( + input clkcpu, + + input wr, // write to the page table + input [1:0] page_size, + input spvmd, + input osmd, + input mem_write, + + input [25:0] addr_i, + output [25:0] addr_o, + output valid +); + +localparam PAGE_TABLE_SIZE = 128; + +// Memory protection truth table. +// | 00 | 01 | 10 | 11 | +// -----|------|------|------|------| +// SPVMD| R/W | R/W | R/W | R/W | +// OSMD| R/W | R/W | R | R | +// USRMD| R/W | R | - | - | +// |------|------|------|------| + +// address translation table. + +// TODO: other memory sizes? +// if the OS uses different memory sizes at startup i'll implement it +// otherwise i'll make it fixed at synth time. + +// ppn swizzle for 32K page size. +// could potentially get 16Mb here by making 512 pages. +wire [6:0] ppn = page_size == 2'b00 ? {addr_i[6:0]} : + page_size == 2'b01 ? {addr_i[0], addr_i[6:1]} : + page_size == 2'b10 ? {addr_i[1:0], addr_i[6:2]} : + {addr_i[1], addr_i[2], addr_i[0], addr_i[6:3]}; + +genvar c; +generate + for (c = 0; c < PAGE_TABLE_SIZE; c = c + 1) begin: pgentry + + reg[14:0] r = 0; // register for this table entry. + + wire prot = spvmd | (osmd & ~mem_write) | (osmd & mem_write & r[14]) | ~r[14] & r[13] & ~mem_write | ~r[14] & ~r[13]; + + wire en = r[12:3] == addr_i[24:15] & prot; // lookup logic when this table is active. + wire sel = ppn[6:0] == c[6:0]; // select logic for this page table (for writing table) + wire [25:0] addr = {4'b0000, c[6:0], addr_i[14:0]}; + + always @(posedge clkcpu) begin + + if (wr & sel) begin + + // code to program the table + r <= {addr_i[9:8], addr_i[11:10], addr_i[22:12]}; + $display("writing to table entry %d := %x (%x)", c, {addr_i[9:8], addr_i[11:10], addr_i[22:12]}, addr_i); + + end + + end + + end + +endgenerate + +// 128 to 1 decode. +assign addr_o = pgentry[0].en ? pgentry[0].addr : + pgentry[1].en ? pgentry[1].addr : + pgentry[2].en ? pgentry[2].addr : + pgentry[3].en ? pgentry[3].addr : + pgentry[4].en ? pgentry[4].addr : + pgentry[5].en ? pgentry[5].addr : + pgentry[6].en ? pgentry[6].addr : + pgentry[7].en ? pgentry[7].addr : + pgentry[8].en ? pgentry[8].addr : + pgentry[9].en ? pgentry[9].addr : + pgentry[10].en ? pgentry[10].addr : + pgentry[11].en ? pgentry[11].addr : + pgentry[12].en ? pgentry[12].addr : + pgentry[13].en ? pgentry[13].addr : + pgentry[14].en ? pgentry[14].addr : + pgentry[15].en ? pgentry[15].addr : + pgentry[16].en ? pgentry[16].addr : + pgentry[17].en ? pgentry[17].addr : + pgentry[18].en ? pgentry[18].addr : + pgentry[19].en ? pgentry[19].addr : + pgentry[20].en ? pgentry[20].addr : + pgentry[21].en ? pgentry[21].addr : + pgentry[22].en ? pgentry[22].addr : + pgentry[23].en ? pgentry[23].addr : + pgentry[24].en ? pgentry[24].addr : + pgentry[25].en ? pgentry[25].addr : + pgentry[26].en ? pgentry[26].addr : + pgentry[27].en ? pgentry[27].addr : + pgentry[28].en ? pgentry[28].addr : + pgentry[29].en ? pgentry[29].addr : + pgentry[30].en ? pgentry[30].addr : + pgentry[31].en ? pgentry[31].addr : + pgentry[32].en ? pgentry[32].addr : + pgentry[33].en ? pgentry[33].addr : + pgentry[34].en ? pgentry[34].addr : + pgentry[35].en ? pgentry[35].addr : + pgentry[36].en ? pgentry[36].addr : + pgentry[37].en ? pgentry[37].addr : + pgentry[38].en ? pgentry[38].addr : + pgentry[39].en ? pgentry[39].addr : + pgentry[40].en ? pgentry[40].addr : + pgentry[41].en ? pgentry[41].addr : + pgentry[42].en ? pgentry[42].addr : + pgentry[43].en ? pgentry[43].addr : + pgentry[44].en ? pgentry[44].addr : + pgentry[45].en ? pgentry[45].addr : + pgentry[46].en ? pgentry[46].addr : + pgentry[47].en ? pgentry[47].addr : + pgentry[48].en ? pgentry[48].addr : + pgentry[49].en ? pgentry[49].addr : + pgentry[50].en ? pgentry[50].addr : + pgentry[51].en ? pgentry[51].addr : + pgentry[52].en ? pgentry[52].addr : + pgentry[53].en ? pgentry[53].addr : + pgentry[54].en ? pgentry[54].addr : + pgentry[55].en ? pgentry[55].addr : + pgentry[56].en ? pgentry[56].addr : + pgentry[57].en ? pgentry[57].addr : + pgentry[58].en ? pgentry[58].addr : + pgentry[59].en ? pgentry[59].addr : + pgentry[60].en ? pgentry[60].addr : + pgentry[61].en ? pgentry[61].addr : + pgentry[62].en ? pgentry[62].addr : + pgentry[63].en ? pgentry[63].addr : + pgentry[64].en ? pgentry[64].addr : + pgentry[65].en ? pgentry[65].addr : + pgentry[66].en ? pgentry[66].addr : + pgentry[67].en ? pgentry[67].addr : + pgentry[68].en ? pgentry[68].addr : + pgentry[69].en ? pgentry[69].addr : + pgentry[70].en ? pgentry[70].addr : + pgentry[71].en ? pgentry[71].addr : + pgentry[72].en ? pgentry[72].addr : + pgentry[73].en ? pgentry[73].addr : + pgentry[74].en ? pgentry[74].addr : + pgentry[75].en ? pgentry[75].addr : + pgentry[76].en ? pgentry[76].addr : + pgentry[77].en ? pgentry[77].addr : + pgentry[78].en ? pgentry[78].addr : + pgentry[79].en ? pgentry[79].addr : + pgentry[80].en ? pgentry[80].addr : + pgentry[81].en ? pgentry[81].addr : + pgentry[82].en ? pgentry[82].addr : + pgentry[83].en ? pgentry[83].addr : + pgentry[84].en ? pgentry[84].addr : + pgentry[85].en ? pgentry[85].addr : + pgentry[86].en ? pgentry[86].addr : + pgentry[87].en ? pgentry[87].addr : + pgentry[88].en ? pgentry[88].addr : + pgentry[89].en ? pgentry[89].addr : + pgentry[90].en ? pgentry[90].addr : + pgentry[91].en ? pgentry[91].addr : + pgentry[92].en ? pgentry[92].addr : + pgentry[93].en ? pgentry[93].addr : + pgentry[94].en ? pgentry[94].addr : + pgentry[95].en ? pgentry[95].addr : + pgentry[96].en ? pgentry[96].addr : + pgentry[97].en ? pgentry[97].addr : + pgentry[98].en ? pgentry[98].addr : + pgentry[99].en ? pgentry[99].addr : + pgentry[100].en ? pgentry[100].addr : + pgentry[101].en ? pgentry[101].addr : + pgentry[102].en ? pgentry[102].addr : + pgentry[103].en ? pgentry[103].addr : + pgentry[104].en ? pgentry[104].addr : + pgentry[105].en ? pgentry[105].addr : + pgentry[106].en ? pgentry[106].addr : + pgentry[107].en ? pgentry[107].addr : + pgentry[108].en ? pgentry[108].addr : + pgentry[109].en ? pgentry[109].addr : + pgentry[110].en ? pgentry[110].addr : + pgentry[111].en ? pgentry[111].addr : + pgentry[112].en ? pgentry[112].addr : + pgentry[113].en ? pgentry[113].addr : + pgentry[114].en ? pgentry[114].addr : + pgentry[115].en ? pgentry[115].addr : + pgentry[116].en ? pgentry[116].addr : + pgentry[117].en ? pgentry[117].addr : + pgentry[118].en ? pgentry[118].addr : + pgentry[119].en ? pgentry[119].addr : + pgentry[120].en ? pgentry[120].addr : + pgentry[121].en ? pgentry[121].addr : + pgentry[122].en ? pgentry[122].addr : + pgentry[123].en ? pgentry[123].addr : + pgentry[124].en ? pgentry[124].addr : + pgentry[125].en ? pgentry[125].addr : + pgentry[126].en ? pgentry[126].addr : + pgentry[127].en ? pgentry[127].addr : 26'hZZZZZZZ; + +assign valid = pgentry[0].en | pgentry[1].en | pgentry[2].en | pgentry[3].en | pgentry[4].en | pgentry[5].en | pgentry[6].en | pgentry[7].en | + pgentry[8].en | pgentry[9].en | pgentry[10].en | pgentry[11].en | pgentry[12].en | pgentry[13].en | pgentry[14].en | pgentry[15].en | + pgentry[16].en | pgentry[17].en | pgentry[18].en | pgentry[19].en | pgentry[20].en | pgentry[21].en | pgentry[22].en | pgentry[23].en | + pgentry[24].en | pgentry[25].en | pgentry[26].en | pgentry[27].en | pgentry[28].en | pgentry[29].en | pgentry[30].en | pgentry[31].en | + pgentry[32].en | pgentry[33].en | pgentry[34].en | pgentry[35].en | pgentry[36].en | pgentry[37].en | pgentry[38].en | pgentry[39].en | + pgentry[40].en | pgentry[41].en | pgentry[42].en | pgentry[43].en | pgentry[44].en | pgentry[45].en | pgentry[46].en | pgentry[47].en | + pgentry[48].en | pgentry[49].en | pgentry[50].en | pgentry[51].en | pgentry[52].en | pgentry[53].en | pgentry[54].en | pgentry[55].en | + pgentry[56].en | pgentry[57].en | pgentry[58].en | pgentry[59].en | pgentry[60].en | pgentry[61].en | pgentry[62].en | pgentry[63].en | + pgentry[64].en | pgentry[65].en | pgentry[66].en | pgentry[67].en | pgentry[68].en | pgentry[69].en | pgentry[70].en | pgentry[71].en | + pgentry[72].en | pgentry[73].en | pgentry[74].en | pgentry[75].en | pgentry[76].en | pgentry[77].en | pgentry[78].en | pgentry[79].en | + pgentry[80].en | pgentry[81].en | pgentry[82].en | pgentry[83].en | pgentry[84].en | pgentry[85].en | pgentry[86].en | pgentry[87].en | + pgentry[88].en | pgentry[89].en | pgentry[90].en | pgentry[91].en | pgentry[92].en | pgentry[93].en | pgentry[94].en | pgentry[95].en | + pgentry[96].en | pgentry[97].en | pgentry[98].en | pgentry[99].en | pgentry[100].en | pgentry[101].en | pgentry[102].en | pgentry[103].en | + pgentry[104].en | pgentry[105].en | pgentry[106].en | pgentry[107].en | pgentry[108].en | pgentry[109].en | pgentry[110].en | pgentry[111].en | + pgentry[112].en | pgentry[113].en | pgentry[114].en | pgentry[115].en | pgentry[116].en | pgentry[117].en | pgentry[118].en | pgentry[119].en | + pgentry[120].en | pgentry[121].en | pgentry[122].en | pgentry[123].en | pgentry[124].en | pgentry[125].en | pgentry[126].en | pgentry[127].en; + +endmodule diff --git a/podules.v b/podules.v new file mode 100644 index 0000000..5c8d784 --- /dev/null +++ b/podules.v @@ -0,0 +1,80 @@ +`timescale 1ns / 1ps +/* podules.v + + Copyright (c) 2015, Stephen J. Leary + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the nor the + * names of its contributors may be used to endorse or promote products + * derived from this software 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 BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +module podules( + + input clkcpu, // system cpu clock. + input clk8m_en, // goes high in sync with 32m clock to give simulated 8mhz + input clk2m_en, // goes high in sync with 32m clock to give simulated 2mhz + + input rst_i, // reset + + input [1:0] speed_i, // podule access speed. (redundant except for address decode). + + // "wishbone bus" the ack is externally generated currently. + input wb_cyc, + input wb_stb, + input wb_we, + + input [15:2] wb_adr, // la + input [15:0] wb_dat_i, // bd + output[15:0] wb_dat_o // bd + + // place any signals that need to be passed up to the top after here. +); + +localparam PODULE0 = 2'b00; +localparam PODULE1 = 2'b01; +localparam PODULE2 = 2'b10; +localparam PODULE3 = 2'b11; + +wire [1:0] podule_addr = wb_adr[15:14]; +wire [3:0] podule_select = podule_addr == PODULE0 ? 4'b0001 : + podule_addr == PODULE1 ? 4'b0010 : + podule_addr == PODULE2 ? 4'b0100 : + podule_addr == PODULE3 ? 4'b1000 : 4'd0; + +wire [15:0] pod0_dat; +wire [15:0] pod1_dat; +wire [15:0] pod2_dat; +wire [15:0] pod3_dat; + + +always @(posedge clkcpu) begin + + + +end + +// emulate a simple podule as a test for *PODULES +assign pod0_dat = wb_adr[13:2] == 12'd0 ? {8'd0, 8'b0_1010_000} : 16'hFFFF; + +assign wb_dat_o = podule_select[PODULE0] ? pod0_dat : 16'hFFFF; + +endmodule diff --git a/registerInterface.v b/registerInterface.v new file mode 100644 index 0000000..33370de --- /dev/null +++ b/registerInterface.v @@ -0,0 +1,94 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// registerInterface.v //// +//// //// +//// This file is part of the i2cSlave opencores effort. +//// //// +//// //// +//// Module Description: //// +//// You will need to modify this file to implement your +//// interface. +//// Add your control and status bytes/bits to module inputs and outputs, +//// and also to the I2C read and write process blocks +//// //// +//// To Do: //// +//// +//// //// +//// Author(s): //// +//// - Steve Fielding, sfielding@base2designs.com //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2008 Steve Fielding and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from //// +//// //// +////////////////////////////////////////////////////////////////////// +// +`include "i2cSlave_define.v" + + +module registerInterface ( + input clk, + input [7:0] addr, + input [7:0] dataIn, + input writeEn, + output reg [7:0] dataOut +); + + localparam MEM_DEPTH = 256; + + +reg [7:0] memory[0:MEM_DEPTH-1]; + +integer i; + +initial begin + + $readmemh("cmos.mif", memory); + +end + +// --- I2C Read +always @(posedge clk) begin + casex (addr) + 8'h02: dataOut <= 8'h33; // sec + 8'h03: dataOut <= 8'h33; // mins + 8'h04: dataOut <= 8'h11; // hour + 8'h05: dataOut <= 8'he9; // year + 8'h06: dataOut <= 8'h81; // month/week + 8'h0x: dataOut <= 8'h00; // everything else < 16 + default: dataOut <= memory[addr]; + endcase +end + +// --- I2C Write +always @(posedge clk) begin + if (writeEn == 1'b1) begin + memory[addr] <= dataIn; + end +end + +endmodule + + + diff --git a/sdram_defines.v b/sdram_defines.v new file mode 100644 index 0000000..f931b79 --- /dev/null +++ b/sdram_defines.v @@ -0,0 +1,47 @@ +/* sdram_defines.v + + Copyright (c) 2013-2014, Stephen J. Leary + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Stephen J. Leary nor the + names of its contributors may be used to endorse or promote products + derived from this software 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 STEPHEN J. LEARY 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. +*/ + +localparam RASCAS_DELAY = 3'd3; // tRCD=20ns -> 3 cycles@128MHz +localparam BURST_LENGTH = 3'b000; // 000=1, 001=2, 010=4, 011=8, 111 = continuous. +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 WRITE_BURST = 1'b0; // 0= write burst enabled, 1=only single access write +localparam RFC_DELAY = 4'd7; // tRFC=66ns -> 9 cycles@128MHz + +// 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; \ No newline at end of file diff --git a/sdram_init.v b/sdram_init.v new file mode 100644 index 0000000..73957da --- /dev/null +++ b/sdram_init.v @@ -0,0 +1,101 @@ +/* sdram_init.v + + Copyright (c) 2013-2014, Stephen J. Leary + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Stephen J. Leary nor the + names of its contributors may be used to endorse or promote products + derived from this software 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 STEPHEN J. LEARY BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +module sdram_init( + + input sd_clk, + input sd_rst, + output reg [3:0] sd_cmd, + output reg [12:0] sd_a, // 13 bit multiplexed address bus + output sd_rdy +); + +`include "sdram_defines.v" + +parameter MODE = 0; + +reg [3:0] t; +reg [4:0] reset; + +initial begin + + t = 4'd0; + reset = 5'h1f; + sd_a = 13'd0; + sd_cmd = CMD_INHIBIT; + +end + +always @(posedge sd_clk) begin + + sd_cmd <= CMD_INHIBIT; // default: idle + + if (sd_rst) begin + + t <= 4'd0; + reset <= 5'h1f; + sd_a <= 13'd0; + + end else if (!sd_rdy) begin + + t <= t + 4'd1; + + if (t ==4'hF) begin + reset <= reset - 5'd1; + end + + if (t == 4'h0) begin + + if(reset == 13) begin + $display("precharging all banks"); + sd_cmd <= CMD_PRECHARGE; + sd_a[10] <= 1'b1; // precharge all banks + end + + if(reset == 2) begin + sd_cmd <= CMD_LOAD_MODE; + sd_a <= MODE; + end + + if(reset == 1) begin + $display("loading mode"); + sd_cmd <= CMD_LOAD_MODE; + sd_a <= MODE; + end + + end + + end + +end + +assign sd_rdy = reset == 5'd0; + +endmodule \ No newline at end of file diff --git a/sdram_top.v b/sdram_top.v new file mode 100644 index 0000000..5dc9fb9 --- /dev/null +++ b/sdram_top.v @@ -0,0 +1,415 @@ +/* sdram_top.v + + Copyright (c) 2013-2014, Stephen J. Leary + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Stephen J. Leary nor the + names of its contributors may be used to endorse or promote products + derived from this software 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 STEPHEN J. LEARY BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +module sdram_top ( + + // interface to the MT48LC16M16 chip + input sd_clk, // sdram is accessed at 128MHz + input sd_rst, // reset the sdram controller. + output sd_cke, // clock enable. + inout [15:0] sd_dq, // 16 bit bidirectional data bus + output [12:0] sd_addr, // 13 bit multiplexed address bus + output reg[1:0] sd_dqm = 2'b00, // two byte masks + output reg[1:0] sd_ba = 2'b00, // two banks + output sd_cs_n, // a single chip select + output sd_we_n, // write enable + output sd_ras_n, // row address select + output sd_cas_n, // columns address select + output sd_ready, // sd ready. + + // cpu/chipset interface + + input wb_clk, // 32MHz 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 = 0, // data output to chipset/cpu + output reg wb_ack = 0, + input [23: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 +); + +`include "sdram_defines.v" + +localparam MODE = { 3'b000, NO_WRITE_BURST, OP_MODE, CAS_LATENCY, ACCESS_TYPE, BURST_LENGTH}; + + +reg[31:0] sd_dat = 0; // data output to chipset/cpu +reg[31:0] sd_dat_nxt = 0; // data output to chipset/cpu + +reg sd_stb = 1'b0; // copy of the wishbone bus signal. +reg sd_we = 1'b0; // copy of the wishbone bus signal. +reg sd_wr = 1'b0; +reg sd_cyc = 1'b0; // copy of the wishbone bus signal. +reg sd_burst = 1'b0; + +reg [3:0] sd_cycle= 4'd0; +reg sd_done = 1'b0; + +reg [3:0] sd_cmd = 4'd0; // current command sent to sd ram +reg [12:0] sd_a = 13'd0; +reg [15:0] sd_q = 16'd0; // data to output during write phase. + + +reg [9:0] sd_refresh = 10'd0; +reg sd_auto_refresh = 1'b0; + +wire [3:0] sd_init_cmd; +wire [12:0] sd_init_a; + +wire sd_reading; +wire sd_writing; + +sdram_init # +( + .MODE(MODE) +) +INIT ( + + .sd_clk ( sd_clk ), + .sd_rst ( sd_rst ), + .sd_cmd ( sd_init_cmd ), + .sd_a ( sd_init_a ), + .sd_rdy ( sd_ready ) + +); + + +// output data during the write phase. +assign sd_dq = (sd_wr === 1'b1) ? sd_q : 16'bZZZZZZZZZZZZZZZZ; + +localparam CYCLE_RAS_START = 4'd1; +localparam CYCLE_RFSH_START = CYCLE_RAS_START; +localparam CYCLE_CAS0 = CYCLE_RFSH_START + RASCAS_DELAY; +localparam CYCLE_CAS1 = CYCLE_CAS0 + 4'd1; +localparam CYCLE_CAS2 = CYCLE_CAS1 + 4'd1; +localparam CYCLE_CAS3 = CYCLE_CAS2 + 4'd1; +localparam CYCLE_READ0 = CYCLE_CAS0 + CAS_LATENCY + 4'd2; +localparam CYCLE_READ1 = CYCLE_READ0+ 1'd1; +localparam CYCLE_READ2 = CYCLE_READ1+ 1'd1; +localparam CYCLE_READ3 = CYCLE_READ2+ 1'd1; +localparam CYCLE_END = 4'hF; +localparam CYCLE_WR_END = CYCLE_CAS1 + 4'd4; +localparam CYCLE_RFSH_END = CYCLE_RFSH_START + RFC_DELAY; + +localparam RAM_CLK = 128000000; +localparam REFRESH_PERIOD = (RAM_CLK / (16 * 8192)) - CYCLE_END; + +always @(posedge sd_clk) begin + + // bring the wishbone bus signal into the ram clock domain. + + sd_wr <= 1'b0; // default to not writing. + sd_we <= wb_we; + sd_cmd <= CMD_INHIBIT; + + if (sd_ready) begin + + if (wb_stb & wb_cyc & ~wb_ack) begin + + sd_stb <= wb_stb; + sd_cyc <= wb_cyc; + + end + + sd_refresh <= sd_refresh + 9'd1; + + // this is the auto refresh code. + // it kicks in so that 8192 auto refreshes are + // issued in a 64ms period. Other bus operations + // are stalled during this period. + if ((sd_refresh > REFRESH_PERIOD) && (sd_cycle == 4'd0)) begin + + sd_auto_refresh <= 1'b1; + sd_refresh <= 10'd0; + + end else if (sd_auto_refresh) begin + + // while the cycle is active count. + sd_cycle <= sd_cycle + 3'd1; + + case (sd_cycle) + + CYCLE_RFSH_START: begin + + sd_cmd <= CMD_AUTO_REFRESH; + + end + + CYCLE_RFSH_END: begin + + // reset the count. + sd_auto_refresh <= 1'b0; + sd_cycle <= 4'd0; + + end + + endcase + + end else if (sd_cyc | (sd_cycle != 0)) begin + + // while the cycle is active count. + sd_cycle <= sd_cycle + 3'd1; + //sd_cmd <= CMD_NOP; + + case (sd_cycle) + + CYCLE_RAS_START: begin + + sd_cmd <= CMD_ACTIVE; + sd_a <= { 1'b0, wb_adr[20:9] }; + sd_ba <= wb_adr[22:21]; + + if(sd_reading) begin + sd_dqm <= 2'b00; + end else begin + sd_dqm <= 2'b11; + end + + end + + // this is the first CAS cycle + CYCLE_CAS0: begin + + // always, always read on a 32bit boundary and completely ignore the lsb of wb_adr. + sd_a <= { 4'b0000, wb_adr[23], wb_adr[8:2], 1'b0 }; // no auto precharge + sd_dqm <= ~wb_sel[1:0]; + + if (sd_reading) begin + + sd_cmd <= CMD_READ; + + end else if (sd_writing) begin + + sd_cmd <= CMD_WRITE; + sd_q <= wb_dat_i[15:0]; + sd_wr <= 1'b1; + + end + + end + + CYCLE_CAS1: begin + + // now we access the second part of the 32 bit location. + sd_a <= { 4'b0010, wb_adr[23], wb_adr[8:2], 1'b1 }; // auto precharge + sd_dqm <= ~wb_sel[3:2]; + + if (sd_reading) begin + + sd_cmd <= CMD_READ; + + if (burst_mode & can_burst) begin + + sd_a[10] <= 1'b0; + sd_burst <= 1'b1; + + end + + end else if (sd_writing) begin + + sd_cmd <= CMD_WRITE; + sd_q <= wb_dat_i[31:16]; + sd_done <= 1'b1; + sd_wr <= 1'b1; + + end + + end + + CYCLE_CAS2: begin + + if (sd_burst) begin + + // always, always read on a 32bit boundary and completely ignore the lsb of wb_adr. + sd_a <= { 4'b0000, wb_adr[23], wb_adr[8:3], 2'b10 }; // no auto precharge + sd_dqm <= ~wb_sel[1:0]; + + if (sd_reading) begin + + sd_cmd <= CMD_READ; + + end + + end + + end + + CYCLE_CAS3: begin + + if (sd_burst) begin + + // always, always read on a 32bit boundary and completely ignore the lsb of wb_adr. + sd_a <= { 4'b0010, wb_adr[23], wb_adr[8:3], 2'b11 }; // no auto precharge + sd_dqm <= ~wb_sel[3:2]; + + if (sd_reading) begin + + sd_cmd <= CMD_READ; + + end + + end + + end + + CYCLE_READ0: begin + + if (sd_writing) begin + // if we are writing then the sd_done signal has been high for + // enough clock cycles. we can end the cycle here. + sd_done <= 1'b0; + sd_cycle <= 4'd0; + sd_cyc <= 1'b0; + sd_stb <= 1'b0; + + end + + if (sd_reading) begin + + sd_dat[15:0] <= sd_dq; + + end + + end + + CYCLE_READ1: begin + + if (sd_reading) begin + + sd_dat[31:16] <= sd_dq; + sd_done <= 1'b1; + + end + + end + + CYCLE_READ2: begin + + if (sd_reading) begin + + sd_dat_nxt[15:0] <= sd_dq; + + end + + end + + CYCLE_READ3: begin + + if (sd_reading) begin + + sd_dat_nxt[31:16] <= sd_dq; + + end + + end + + CYCLE_END: begin + sd_burst <= 1'b0; + sd_done <= 1'b0; + sd_cyc <= 1'b0; + sd_stb <= 1'b0; + end + + endcase + + + end else begin + + + sd_done <= 1'd0; + sd_cycle <= 4'd0; + sd_burst <= 1'b0; + + end + + end else begin + + + + sd_stb <= 1'b0; + sd_cyc <= 1'b0; + sd_burst <= 1'b0; + + sd_cycle <= 4'd0; + sd_done <= 1'b0; + + end + + +end + +reg wb_burst; + +always @(posedge wb_clk) begin + + wb_ack <= sd_done & ~wb_ack; + + if (wb_stb & wb_cyc) begin + + if (sd_done & ~wb_ack) begin + + wb_dat_o <= sd_dat; + wb_burst <= burst_mode; + + end + + if (wb_ack & wb_burst) begin + + wb_ack <= 1'b1; + wb_burst <= 1'b0; + wb_dat_o <= sd_dat_nxt; + + end + + + end else begin + + wb_burst <= 1'b0; + + end + + +end + +wire burst_mode = wb_cti == 3'b010; +wire can_burst = wb_adr[2] === 1'b0; +assign sd_reading = sd_stb & sd_cyc & ~sd_we; +assign sd_writing = sd_stb & sd_cyc & sd_we; + +// drive control signals according to current command +assign sd_cs_n = sd_ready ? sd_cmd[3] : sd_init_cmd[3]; +assign sd_ras_n = sd_ready ? sd_cmd[2] : sd_init_cmd[2]; +assign sd_cas_n = sd_ready ? sd_cmd[1] : sd_init_cmd[1]; +assign sd_we_n = sd_ready ? sd_cmd[0] : sd_init_cmd[0]; +assign sd_addr = sd_ready ? sd_a : sd_init_a; +assign sd_cke = 1'b1; + +endmodule diff --git a/serialInterface.v b/serialInterface.v new file mode 100644 index 0000000..5a237cc --- /dev/null +++ b/serialInterface.v @@ -0,0 +1,365 @@ + +////////////////////////////////////////////////////////////////////// +//// //// +//// serialInterface.v //// +//// //// +//// This file is part of the i2cSlave opencores effort. +//// //// +//// //// +//// Module Description: //// +//// Perform all serial to parallel, and parallel +//// to serial conversions. Perform device address matching +//// Handle arbitrary length I2C reads terminated by NAK +//// from host, and arbitrary length I2C writes terminated +//// by STOP from host +//// The second byte of a I2C write is always interpreted +//// as a register address, and becomes the base register address +//// for all read and write transactions. +//// I2C WRITE: devAddr, regAddr, data[regAddr], data[regAddr+1], ..... data[regAddr+N] +//// I2C READ: data[regAddr], data[regAddr+1], ..... data[regAddr+N] +//// Note that when regAddR reaches 255 it will automatically wrap round to 0 +//// //// +//// To Do: //// +//// +//// //// +//// Author(s): //// +//// - Steve Fielding, sfielding@base2designs.com //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2008 Steve Fielding and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source 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 Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from //// +//// //// +////////////////////////////////////////////////////////////////////// +// +`include "timescale.v" +`include "i2cSlave_define.v" + +module serialInterface (clearStartStopDet, clk, dataIn, dataOut, regAddr, rst, scl, sdaIn, sdaOut, startStopDetState, writeEn); +input clk; +input [7:0]dataIn; +input rst; +input scl; +input sdaIn; +input [1:0]startStopDetState; +output clearStartStopDet; +output [7:0]dataOut; +output [7:0]regAddr; +output sdaOut; +output writeEn; + +reg clearStartStopDet, next_clearStartStopDet; +wire clk; +wire [7:0]dataIn; +reg [7:0]dataOut, next_dataOut; +reg [7:0]regAddr, next_regAddr; +wire rst; +wire scl; +wire sdaIn; +reg sdaOut, next_sdaOut; +wire [1:0]startStopDetState; +reg writeEn, next_writeEn; + +// diagram signals declarations +reg [2:0]bitCnt, next_bitCnt; +reg [7:0]rxData, next_rxData; +reg [1:0]streamSt, next_streamSt; +reg [7:0]txData, next_txData; + +// BINARY ENCODED state machine: SISt +// State codes definitions: +`define START 4'b0000 +`define CHK_RD_WR 4'b0001 +`define READ_RD_LOOP 4'b0010 +`define READ_WT_HI 4'b0011 +`define READ_CHK_LOOP_FIN 4'b0100 +`define READ_WT_LO 4'b0101 +`define READ_WT_ACK 4'b0110 +`define WRITE_WT_LO 4'b0111 +`define WRITE_WT_HI 4'b1000 +`define WRITE_CHK_LOOP_FIN 4'b1001 +`define WRITE_LOOP_WT_LO 4'b1010 +`define WRITE_ST_LOOP 4'b1011 +`define WRITE_WT_LO2 4'b1100 +`define WRITE_WT_HI2 4'b1101 +`define WRITE_CLR_WR 4'b1110 +`define WRITE_CLR_ST_STOP 4'b1111 + +reg [3:0]CurrState_SISt, NextState_SISt; + +// Diagram actions (continuous assignments allowed only: assign ...) +// diagram ACTION + + +// Machine: SISt + +// NextState logic (combinatorial) +always @ (startStopDetState or streamSt or scl or txData or bitCnt or rxData or sdaIn or regAddr or dataIn or sdaOut or writeEn or dataOut or clearStartStopDet or CurrState_SISt) +begin + NextState_SISt <= CurrState_SISt; + // Set default values for outputs and signals + next_streamSt <= streamSt; + next_txData <= txData; + next_rxData <= rxData; + next_sdaOut <= sdaOut; + next_writeEn <= writeEn; + next_dataOut <= dataOut; + next_bitCnt <= bitCnt; + next_clearStartStopDet <= clearStartStopDet; + next_regAddr <= regAddr; + case (CurrState_SISt) // synopsys parallel_case full_case + `START: + begin + next_streamSt <= `STREAM_IDLE; + next_txData <= 8'h00; + next_rxData <= 8'h00; + next_sdaOut <= 1'b1; + next_writeEn <= 1'b0; + next_dataOut <= 8'h00; + next_bitCnt <= 3'b000; + next_clearStartStopDet <= 1'b0; + NextState_SISt <= `CHK_RD_WR; + end + `CHK_RD_WR: + begin + if (streamSt == `STREAM_READ) + begin + NextState_SISt <= `READ_RD_LOOP; + next_txData <= dataIn; + next_regAddr <= regAddr + 1'b1; + next_bitCnt <= 3'b001; + end + else + begin + NextState_SISt <= `WRITE_WT_HI; + next_rxData <= 8'h00; + end + end + `READ_RD_LOOP: + begin + if (scl == 1'b0) + begin + NextState_SISt <= `READ_WT_HI; + next_sdaOut <= txData [7]; + next_txData <= {txData [6:0], 1'b0}; + end + end + `READ_WT_HI: + begin + if (scl == 1'b1) + begin + NextState_SISt <= `READ_CHK_LOOP_FIN; + end + end + `READ_CHK_LOOP_FIN: + begin + if (bitCnt == 3'b000) + begin + NextState_SISt <= `READ_WT_LO; + end + else + begin + NextState_SISt <= `READ_RD_LOOP; + next_bitCnt <= bitCnt + 1'b1; + end + end + `READ_WT_LO: + begin + if (scl == 1'b0) + begin + NextState_SISt <= `READ_WT_ACK; + next_sdaOut <= 1'b1; + end + end + `READ_WT_ACK: + begin + if (scl == 1'b1) + begin + NextState_SISt <= `CHK_RD_WR; + if (sdaIn == `I2C_NAK) + next_streamSt <= `STREAM_IDLE; + end + end + `WRITE_WT_LO: + begin + if ((scl == 1'b0) && (startStopDetState == `STOP_DET || + (streamSt == `STREAM_IDLE && startStopDetState == `NULL_DET))) + begin + NextState_SISt <= `WRITE_CLR_ST_STOP; + case (startStopDetState) + `NULL_DET: + next_bitCnt <= bitCnt + 1'b1; + `START_DET: begin + next_streamSt <= `STREAM_IDLE; + next_rxData <= 8'h00; + end + default: ; + endcase + next_streamSt <= `STREAM_IDLE; + next_clearStartStopDet <= 1'b1; + end + else if (scl == 1'b0) + begin + NextState_SISt <= `WRITE_ST_LOOP; + case (startStopDetState) + `NULL_DET: + next_bitCnt <= bitCnt + 1'b1; + `START_DET: begin + next_streamSt <= `STREAM_IDLE; + next_rxData <= 8'h00; + end + default: ; + endcase + end + end + `WRITE_WT_HI: + begin + if (scl == 1'b1) + begin + NextState_SISt <= `WRITE_WT_LO; + next_rxData <= {rxData [6:0], sdaIn}; + next_bitCnt <= 3'b000; + end + end + `WRITE_CHK_LOOP_FIN: + begin + if (bitCnt == 3'b111) + begin + NextState_SISt <= `WRITE_CLR_WR; + next_sdaOut <= `I2C_ACK; + case (streamSt) + `STREAM_IDLE: begin + if (rxData[7:1] == `I2C_ADDRESS && + startStopDetState == `START_DET) begin + if (rxData[0] == 1'b1) + next_streamSt <= `STREAM_READ; + else + next_streamSt <= `STREAM_WRITE_ADDR; + end + else + next_sdaOut <= `I2C_NAK; + end + `STREAM_WRITE_ADDR: begin + next_streamSt <= `STREAM_WRITE_DATA; + next_regAddr <= rxData; + end + `STREAM_WRITE_DATA: begin + next_dataOut <= rxData; + next_writeEn <= 1'b1; + end + default: + next_streamSt <= streamSt; + endcase + end + else + begin + NextState_SISt <= `WRITE_ST_LOOP; + next_bitCnt <= bitCnt + 1'b1; + end + end + `WRITE_LOOP_WT_LO: + begin + if (scl == 1'b0) + begin + NextState_SISt <= `WRITE_CHK_LOOP_FIN; + end + end + `WRITE_ST_LOOP: + begin + if (scl == 1'b1) + begin + NextState_SISt <= `WRITE_LOOP_WT_LO; + next_rxData <= {rxData [6:0], sdaIn}; + end + end + `WRITE_WT_LO2: + begin + if (scl == 1'b0) + begin + NextState_SISt <= `CHK_RD_WR; + next_sdaOut <= 1'b1; + end + end + `WRITE_WT_HI2: + begin + next_clearStartStopDet <= 1'b0; + if (scl == 1'b1) + begin + NextState_SISt <= `WRITE_WT_LO2; + end + end + `WRITE_CLR_WR: + begin + if (writeEn == 1'b1) + next_regAddr <= regAddr + 1'b1; + next_writeEn <= 1'b0; + next_clearStartStopDet <= 1'b1; + NextState_SISt <= `WRITE_WT_HI2; + end + `WRITE_CLR_ST_STOP: + begin + next_clearStartStopDet <= 1'b0; + NextState_SISt <= `CHK_RD_WR; + end + endcase +end + +// Current State Logic (sequential) +always @ (posedge clk) +begin + if (rst == 1'b1) + CurrState_SISt <= `START; + else + CurrState_SISt <= NextState_SISt; +end + +// Registered outputs logic +always @ (posedge clk) +begin + if (rst == 1'b1) + begin + sdaOut <= 1'b1; + writeEn <= 1'b0; + dataOut <= 8'h00; + clearStartStopDet <= 1'b0; + // regAddr <= // Initialization in the reset state or default value required!! + streamSt <= `STREAM_IDLE; + txData <= 8'h00; + rxData <= 8'h00; + bitCnt <= 3'b000; + end + else + begin + sdaOut <= next_sdaOut; + writeEn <= next_writeEn; + dataOut <= next_dataOut; + clearStartStopDet <= next_clearStartStopDet; + regAddr <= next_regAddr; + streamSt <= next_streamSt; + txData <= next_txData; + rxData <= next_rxData; + bitCnt <= next_bitCnt; + end +end + +endmodule \ No newline at end of file diff --git a/sram_byte_en.v b/sram_byte_en.v new file mode 100644 index 0000000..33c2d7c --- /dev/null +++ b/sram_byte_en.v @@ -0,0 +1,62 @@ +`timescale 1 ps / 1 ps + +module sram_byte_en +#( +parameter DATA_WIDTH = 128, +parameter ADDRESS_WIDTH = 7 +) +( +input i_clk, +input [DATA_WIDTH-1:0] i_write_data, +input i_write_enable, +input [ADDRESS_WIDTH-1:0] i_address, +input [DATA_WIDTH/8-1:0] i_byte_enable, +output [DATA_WIDTH-1:0] o_read_data +); + +wire [DATA_WIDTH-1:0] sub_wire0; +assign o_read_data = sub_wire0; + +altsyncram altsyncram_component ( + .address_a (i_address), + .byteena_a (i_byte_enable), + .clock0 (i_clk), + .data_a (i_write_data), + .wren_a (i_write_enable), + .q_a (sub_wire0), + .aclr0 (1'b0), + .aclr1 (1'b0), + .address_b (1'b1), + .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 (1'b1), + .eccstatus (), + .q_b (), + .rden_a (1'b1), + .rden_b (1'b1), + .wren_b (1'b0)); + +defparam +altsyncram_component.byte_size = 8, +altsyncram_component.clock_enable_input_a = "BYPASS", +altsyncram_component.clock_enable_output_a = "BYPASS", +altsyncram_component.intended_device_family = "Cyclone III", +altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO", +altsyncram_component.lpm_type = "altsyncram", +altsyncram_component.numwords_a = 2**ADDRESS_WIDTH, +altsyncram_component.operation_mode = "SINGLE_PORT", +altsyncram_component.outdata_aclr_a = "NONE", +altsyncram_component.outdata_reg_a = "CLOCK0", +altsyncram_component.power_up_uninitialized = "FALSE", +altsyncram_component.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ", +altsyncram_component.widthad_a = ADDRESS_WIDTH, +altsyncram_component.width_a = DATA_WIDTH, +altsyncram_component.width_byteena_a = DATA_WIDTH/8; + +endmodule \ No newline at end of file diff --git a/sram_line_en.v b/sram_line_en.v new file mode 100644 index 0000000..63f68b5 --- /dev/null +++ b/sram_line_en.v @@ -0,0 +1,60 @@ +`timescale 1 ps / 1 ps + +module sram_line_en +#( +parameter DATA_WIDTH = 128, +parameter ADDRESS_WIDTH = 7, +parameter INITIALIZE_TO_ZERO = 0 +) +( +input i_clk, +input [ADDRESS_WIDTH-1:0] i_address, +input [DATA_WIDTH-1:0] i_write_data, +input i_write_enable, +output [DATA_WIDTH-1:0] o_read_data +); + +wire [DATA_WIDTH-1:0] sub_wire0; +assign o_read_data = sub_wire0; + +altsyncram altsyncram_component ( + .address_a (i_address), + .clock0 (i_clk), + .data_a (i_write_data), + .wren_a (i_write_enable), + .q_a (sub_wire0), + .aclr0 (1'b0), + .aclr1 (1'b0), + .address_b (1'b1), + .addressstall_a (1'b0), + .addressstall_b (1'b0), + .byteena_a (1'b1), + .byteena_b (1'b1), + .clock1 (1'b1), + .clocken0 (1'b1), + .clocken1 (1'b1), + .clocken2 (1'b1), + .clocken3 (1'b1), + .data_b (1'b1), + .eccstatus (), + .q_b (), + .rden_a (1'b1), + .rden_b (1'b1), + .wren_b (1'b0)); +defparam + altsyncram_component.clock_enable_input_a = "BYPASS", + altsyncram_component.clock_enable_output_a = "BYPASS", + altsyncram_component.intended_device_family = "Cyclone III", + altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO", + altsyncram_component.lpm_type = "altsyncram", + altsyncram_component.numwords_a = 2**ADDRESS_WIDTH, + altsyncram_component.operation_mode = "SINGLE_PORT", + altsyncram_component.outdata_aclr_a = "NONE", + altsyncram_component.outdata_reg_a = "CLOCK0", + altsyncram_component.power_up_uninitialized = "FALSE", + altsyncram_component.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ", + altsyncram_component.widthad_a = ADDRESS_WIDTH, + altsyncram_component.width_a = DATA_WIDTH, + altsyncram_component.width_byteena_a = 1; + +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..7dced55 --- /dev/null +++ b/sys/hps_io.v @@ -0,0 +1,434 @@ +// +// hps_io.v (Archie only) +// +// 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. +// + +// WIDE=1 for 16 bit file I/O +// VDNUM 1-4 +module hps_io #(parameter STRLEN=0, WIDE=0, VDNUM=1) +( + 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 [3:0] ioctl_sel, + output reg ioctl_wr, + output reg [24:0] ioctl_addr, // in WIDE mode address will be incremented by 2 + output [31:0] ioctl_dout, + input ioctl_wait, + + input [31:0] fdc_status_out, + output reg [31:0] fdc_status_in, + output reg fdc_data_in_strobe, + output reg [7:0] fdc_data_in, + + // RTC MSM6242B layout + output reg [63:0] RTC, + + input [7:0] kbd_out_data, + input kbd_out_strobe, + output reg [7:0] kbd_in_data, + output reg kbd_in_strobe +); + +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; + + reg old_out_strobe = 0; + reg kbd_out_data_available = 0; + + 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_in_strobe <= 0; + old_out_strobe <= kbd_out_strobe; + if(~old_out_strobe && kbd_out_strobe) kbd_out_data_available <= 1; + + fdc_data_in_strobe <= 0; + + if(~io_enable) begin + 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; + end else begin + + case(cmd) + // buttons and switches + 'h01: cfg <= io_din[7:0]; + 'h02: joystick_0 <= io_din; + 'h03: joystick_1 <= io_din; + + 'h04: begin + if(byte_cnt == 1) begin + io_dout[7:0] <= { 4'ha, 3'b000, kbd_out_data_available }; + kbd_out_data_available <= 0; + end else begin + io_dout[7:0] <= kbd_out_data; + end + end + + 'h05: begin + if(byte_cnt == 1) kbd_in_strobe <= 1; + kbd_in_data <= io_din[7:0]; + 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; + + //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 + + 'h55: //ARCHIE_FDC_GET_STATUS: + begin + if(byte_cnt == 1) io_dout[7:0] <= fdc_status_out[31:24]; + if(byte_cnt == 2) io_dout[7:0] <= fdc_status_out[23:16]; + if(byte_cnt == 3) io_dout[7:0] <= fdc_status_out[15:8]; + if(byte_cnt == 4) io_dout[7:0] <= fdc_status_out[7:0]; + end + + 'h56: //ARCHIE_FDC_TX_DATA: + begin + fdc_data_in_strobe <= 1; + fdc_data_in <= io_din[7:0]; + end + + 'h57: //ARCHIE_FDC_SET_STATUS: + begin + if(byte_cnt == 1) fdc_status_in[31:24] <= io_din[7:0]; + if(byte_cnt == 2) fdc_status_in[23:16] <= io_din[7:0]; + if(byte_cnt == 3) fdc_status_in[15:8] <= io_din[7:0]; + if(byte_cnt == 4) fdc_status_in[7:0] <= io_din[7:0]; + end + endcase + end + end + end +end + +/////////////////////////////// DOWNLOADING /////////////////////////////// + +localparam UIO_FILE_TX = 8'h53; +localparam UIO_FILE_TX_DAT = 8'h54; + +assign ioctl_sel = ioctl_addr[1] ? 4'b1100 : 4'b0011; +assign ioctl_dout = {data,data}; + +reg [15:0] data; + +always@(posedge clk_sys) begin + reg [15:0] cmd; + reg has_cmd; + reg [24:0] addr; + reg wr; + + 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_TX: + begin + if(io_din[7:0]) begin + addr <= 25'h400000; + ioctl_download <= 1; + end else begin + ioctl_addr <= addr; + ioctl_download <= 0; + end + end + + UIO_FILE_TX_DAT: + begin + ioctl_addr <= addr; + data <= io_din; + wr <= 1; + addr <= addr + 2'd2; + end + endcase + end + end + end +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..133b0ae --- /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::SW50ZWdlci1OIFBMTA==::UExMIE1vZGU=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "ZnJhY3Rpb25hbF92Y29fbXVsdGlwbGllcg==::ZmFsc2U=::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==::MQ==::TXVsdGlwbHkgRmFjdG9yIChNLUNvdW50ZXIp" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2ZyYWNfbXVsdGlwbHlfZmFjdG9y::MQ==::RnJhY3Rpb25hbCBNdWx0aXBseSBGYWN0b3IgKEsp" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3Jfbg==::MQ==::RGl2aWRlIEZhY3RvciAoTi1Db3VudGVyKQ==" +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::MTI4LjA=::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzA=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Iw::NjQ=::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjA=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMA==::MjU=::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::MzIuMA==::RGVzaXJlZCBGcmVxdWVuY3k=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2RpdmlkZV9mYWN0b3JfYzE=::MQ==::RGl2aWRlIEZhY3RvciAoQy1Db3VudGVyKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9tdWx0aXBseV9mYWN0b3Ix::NjQ=::QWN0dWFsIE11bHRpcGx5IEZhY3Rvcg==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9mcmFjX211bHRpcGx5X2ZhY3RvcjE=::MQ==::QWN0dWFsIEZyYWN0aW9uYWwgTXVsdGlwbHkgRmFjdG9yIChLKQ==" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "Z3VpX2FjdHVhbF9kaXZpZGVfZmFjdG9yMQ==::MTAw::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==::MA==::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::NTAuMA==::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::NjQ=::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==::NjU=::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::NTAuMTc1::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::MTI4::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==::MTMw::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::MTI4::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==::MTM1::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=::MTI4LjAwMDAwMCBNSHo=::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=::MzIuMDAwMDAwIE1Ieg==::b3V0cHV0X2Nsb2NrX2ZyZXF1ZW5jeTE=" +set_global_assignment -entity "pll_0002" -library "pll" -name IP_COMPONENT_PARAMETER "cGhhc2Vfc2hpZnQx::MCBwcw==::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=::MzIsMzIsMywyLGZhbHNlLGZhbHNlLGZhbHNlLHRydWUsMywyLDEsMCxwaF9tdXhfY2xrLGZhbHNlLHRydWUsMTAsMTAsMSwwLHBoX211eF9jbGssZmFsc2UsZmFsc2UsMSwyMCw2MDAwLDY0MC4wIE1IeiwxLG5vbmUsZ2xiLG1fY250LHBoX211eF9jbGssdHJ1ZQ==::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..55b8f2e --- /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..aec45eb --- /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_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..64bc2aa --- /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("false"), + .reference_clock_frequency("50.0 MHz"), + .operation_mode("direct"), + .number_of_clocks(2), + .output_clock_frequency0("128.000000 MHz"), + .phase_shift0("0 ps"), + .duty_cycle0(50), + .output_clock_frequency1("32.000000 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_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..7828cd8 --- /dev/null +++ b/sys/sdram.sv @@ -0,0 +1,262 @@ +// +// sdram.v +// +// Static RAM controller implementation using SDRAM MT48LC16M16A2 +// +// Copyright (c) 2015,2016 Sorgelig +// +// Some parts of SDRAM code used from project: +// http://hamsterworks.co.nz/mediawiki/index.php/Simple_SDRAM_Controller +// +// 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 . +// +// ------------------------------------------ +// +// v2.1 - Add universal 8/16 bit mode. +// + +module sdram +( + input init, // reset to initialize RAM + input clk, // clock ~100MHz + // + // SDRAM_* - signals to the MT48LC16M16 chip + inout reg [15:0] SDRAM_DQ, // 16 bit bidirectional data bus + output reg [12:0] SDRAM_A, // 13 bit multiplexed address bus + output reg SDRAM_DQML, // two byte masks + output reg SDRAM_DQMH, // + output reg [1:0] SDRAM_BA, // two banks + output SDRAM_nCS, // a single chip select + output SDRAM_nWE, // write enable + output SDRAM_nRAS, // row address select + output SDRAM_nCAS, // columns address select + output SDRAM_CKE, // clock enable + // + input [1:0] wtbt, // 16bit mode: bit1 - write high byte, bit0 - write low byte, + // 8bit mode: 2'b00 - use addr[0] to decide which byte to write + // Ignored while reading. + // + input [24:0] addr, // 25 bit address for 8bit mode. addr[0] = 0 for 16bit mode for correct operations. + output [15:0] dout, // data output to cpu + input [15:0] din, // data input from cpu + input we, // cpu requests write + input rd, // cpu requests read + output reg ready // dout is valid. Ready to accept new read/write. +); + +assign SDRAM_nCS = command[3]; +assign SDRAM_nRAS = command[2]; +assign SDRAM_nCAS = command[1]; +assign SDRAM_nWE = command[0]; +assign SDRAM_CKE = cke; +assign dout = latched ? data_l : data_d; + +// no burst configured +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 for < 100MHz, 3 for >100MHz +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}; + +localparam sdram_startup_cycles= 14'd12100;// 100us, plus a little more, @ 100MHz +localparam cycles_per_refresh = 14'd780; // (64000*100)/8192-1 Calc'd as (64ms @ 100MHz)/8192 rose +localparam startup_refresh_max = 14'b11111111111111; + +// SDRAM 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 [13:0] refresh_count = startup_refresh_max - sdram_startup_cycles; +reg [3:0] command = CMD_INHIBIT; +reg cke = 0; +reg [24:0] save_addr; + +reg latched; +reg [15:0] data; +wire[15:0] data_l = save_addr[0] ? {data[7:0], data[15:8]} : {data[15:8], data[7:0]}; +wire[15:0] data_d = save_addr[0] ? {SDRAM_DQ[7:0], SDRAM_DQ[15:8]} : {SDRAM_DQ[15:8], SDRAM_DQ[7:0]}; + +typedef enum +{ + STATE_STARTUP, + STATE_OPEN_1, STATE_OPEN_2, + STATE_WRITE, + STATE_READ, + STATE_IDLE, STATE_IDLE_1, STATE_IDLE_2, STATE_IDLE_3, + STATE_IDLE_4, STATE_IDLE_5, STATE_IDLE_6, STATE_IDLE_7 +} state_t; + +always @(posedge clk) begin + reg old_we, old_rd; + reg [CAS_LATENCY:0] data_ready_delay; + + reg [15:0] new_data; + reg [1:0] new_wtbt; + reg new_we; + reg new_rd; + reg save_we = 1; + + state_t state = STATE_STARTUP; + + command <= CMD_NOP; + refresh_count <= refresh_count+1'b1; + + data_ready_delay <= {1'b0, data_ready_delay[CAS_LATENCY:1]}; + + // make it ready 1T in advance + if(data_ready_delay[1]) {latched, ready} <= {1'b0, 1'b1}; + if(data_ready_delay[0]) {latched, data} <= {1'b1, SDRAM_DQ}; + + case(state) + STATE_STARTUP: begin + //------------------------------------------------------------------------ + //-- This is the initial startup state, where we wait for at least 100us + //-- before starting the start sequence + //-- + //-- The initialisation is sequence is + //-- * de-assert SDRAM_CKE + //-- * 100us wait, + //-- * assert SDRAM_CKE + //-- * wait at least one cycle, + //-- * PRECHARGE + //-- * wait 2 cycles + //-- * REFRESH, + //-- * tREF wait + //-- * REFRESH, + //-- * tREF wait + //-- * LOAD_MODE_REG + //-- * 2 cycles wait + //------------------------------------------------------------------------ + cke <= 1; + SDRAM_DQ <= 16'bZZZZZZZZZZZZZZZZ; + SDRAM_DQML <= 1; + SDRAM_DQMH <= 1; + SDRAM_A <= 0; + SDRAM_BA <= 0; + + // All the commands during the startup are NOPS, except these + if(refresh_count == startup_refresh_max-31) begin + // ensure all rows are closed + command <= CMD_PRECHARGE; + SDRAM_A[10] <= 1; // all banks + SDRAM_BA <= 2'b00; + end else if (refresh_count == startup_refresh_max-23) begin + // these refreshes need to be at least tREF (66ns) apart + command <= CMD_AUTO_REFRESH; + end else if (refresh_count == startup_refresh_max-15) + command <= CMD_AUTO_REFRESH; + else if (refresh_count == startup_refresh_max-7) begin + // Now load the mode register + command <= CMD_LOAD_MODE; + SDRAM_A <= MODE; + end + + //------------------------------------------------------ + //-- if startup is complete then go into idle mode, + //-- get prepared to accept a new command, and schedule + //-- the first refresh cycle + //------------------------------------------------------ + if(!refresh_count) begin + state <= STATE_IDLE; + ready <= 1; + refresh_count <= 0; + end + end + + STATE_IDLE_7: state <= STATE_IDLE_6; + STATE_IDLE_6: state <= STATE_IDLE_5; + STATE_IDLE_5: state <= STATE_IDLE_4; + STATE_IDLE_4: state <= STATE_IDLE_3; + STATE_IDLE_3: state <= STATE_IDLE_2; + STATE_IDLE_2: state <= STATE_IDLE_1; + STATE_IDLE_1: begin + SDRAM_DQ <= 16'bZZZZZZZZZZZZZZZZ; + state <= STATE_IDLE; + // mask possible refresh to reduce colliding. + if(refresh_count > cycles_per_refresh) begin + //------------------------------------------------------------------------ + //-- Start the refresh cycle. + //-- This tasks tRFC (66ns), so 6 idle cycles are needed @ 100MHz + //------------------------------------------------------------------------ + state <= STATE_IDLE_7; + command <= CMD_AUTO_REFRESH; + refresh_count <= refresh_count - cycles_per_refresh + 1'd1; + end + end + + STATE_IDLE: begin + // Priority is to issue a refresh if one is outstanding + if(refresh_count > (cycles_per_refresh<<1)) state <= STATE_IDLE_1; + else if(new_rd | new_we) begin + new_we <= 0; + new_rd <= 0; + save_addr<= addr; + save_we <= new_we; + state <= STATE_OPEN_1; + command <= CMD_ACTIVE; + SDRAM_A <= addr[13:1]; + SDRAM_BA <= addr[24:23]; + end + end + + // ACTIVE-to-READ or WRITE delay >20ns (-75) + STATE_OPEN_1: state <= STATE_OPEN_2; + STATE_OPEN_2: begin + SDRAM_A <= {4'b0010, save_addr[22:14]}; + SDRAM_DQML <= save_we & (new_wtbt ? ~new_wtbt[0] : save_addr[0]); + SDRAM_DQMH <= save_we & (new_wtbt ? ~new_wtbt[1] : ~save_addr[0]); + state <= save_we ? STATE_WRITE : STATE_READ; + end + + STATE_READ: begin + state <= STATE_IDLE_5; + command <= CMD_READ; + SDRAM_DQ <= 16'bZZZZZZZZZZZZZZZZ; + + // Schedule reading the data values off the bus + data_ready_delay[CAS_LATENCY] <= 1; + end + + STATE_WRITE: begin + state <= STATE_IDLE_5; + command <= CMD_WRITE; + SDRAM_DQ <= new_wtbt ? new_data : {new_data[7:0], new_data[7:0]}; + ready <= 1; + end + endcase + + if(init) begin + state <= STATE_STARTUP; + refresh_count <= startup_refresh_max - sdram_startup_cycles; + end + + old_we <= we; + if(we & ~old_we) {ready, new_we, new_data, new_wtbt} <= {1'b0, 1'b1, din, wtbt}; + + old_rd <= rd; + if(rd & ~old_rd) begin + if(ready & ~save_we & (save_addr[24:1] == addr[24:1])) save_addr <= addr; + else {ready, new_rd} <= {1'b0, 1'b1}; + 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..63a8d74 --- /dev/null +++ b/sys/sys_top.sdc @@ -0,0 +1,28 @@ +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[0].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..e434cb0 --- /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 = 'hA6; // A6 - Archie. + +// 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/timescale.v b/timescale.v new file mode 100644 index 0000000..edd8d7a --- /dev/null +++ b/timescale.v @@ -0,0 +1,5 @@ +////////////////////////////////////////////////////////////////////// +// timescale.v +////////////////////////////////////////////////////////////////////// +`timescale 1ns / 1ps + diff --git a/vidc.v b/vidc.v new file mode 100644 index 0000000..b19bd20 --- /dev/null +++ b/vidc.v @@ -0,0 +1,386 @@ +`timescale 1ns / 1ps +/* vidc.v + + Copyright (c) 2012-2014, Stephen J. Leary + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the nor the + * names of its contributors may be used to endorse or promote products + * derived from this software 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 BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +module vidc +( + input clkcpu, // cpu bus clock domain + + input clkpix, + output reg cepix, + + // "wishbone" interface + input rst_i, + input vidw, // write to a register. + input [31:0] cpu_dat, + + // dma control. + input [31:0] viddat, + input vidak, + output vidrq, + + input sndak, + output sndrq, + + output flybk, + + // video outputs + output hsync, + output vsync, + + output [3:0] video_r, + output [3:0] video_g, + output [3:0] video_b, + output video_en, + + output [15:0] audio_l, + output [15:0] audio_r +); + +wire cur_enabled; +reg cur_enabled_r; +wire enabled; +wire border; + +// registers +reg [12:0] vidc_palette[0:15]; // palette register. +reg [15:0] vidc_cr; // control register. +reg [12:0] vidc_border; // border register. +reg [12:0] cur_palette[1:3]; // border register. + +// audio clock domain signals +wire [7:0] snd_sam_data; +wire snd_sam_en; + +// pixel clock domain signals +//delayed enable. +reg enabled_d1; +reg enabled_d2; + +reg pix_load; +wire pix_ack; +wire [7:0] pix_data; +reg [2:0] pix_shift_count; +reg [7:0] pix_data_latch = 8'd0; + +// cursor pixel clock signals +reg csr_load; +wire csr_ack; +reg [3:0] csr_load_count; +wire [7:0] csr_data; +reg [2:0] csr_shift_count; +reg [7:0] csr_data_latch = 8'd0; + +// dmacon +wire cur_load; +wire vid_load; +wire snd_load; + +// internal data request lines +wire currq_int; +wire vidrq_int; + +always @(negedge clkpix) begin + reg [2:0] div6 = 0; + reg [1:0] div4 = 0; + + div4 <= div4 + 1'd1; + div6 <= div6 + 1'd1; + if(div6 == 5) div6 <= 0; + + case(vidc_cr[1:0]) + 0: cepix <= !div6; + 1: cepix <= !div4; + 2: cepix <= ((div6 == 0) || (div6 == 3)); + 3: cepix <= !div4[0]; + endcase +end + +vidc_timing TIMING( + + .clkcpu ( clkcpu ), + .wr ( vidw ), + .cpu_dat ( cpu_dat ), + + .clkvid ( clkpix ), + .cevid ( cepix ), + .rst ( rst_i ), + + .o_hsync ( hsync ), + .o_vsync ( vsync ), + .o_flyback ( flybk ), + .o_enabled ( enabled ), + .o_cursor ( cur_enabled ), + .o_border ( border ) +); + +// this module does the math for a DMA channel +vidc_dmachannel VIDEODMA ( + + .rst ( flybk | rst_i ), + .clkcpu ( clkcpu ), + .clkdev ( clkpix ), + .cedev ( cepix ), + + .cpu_data ( viddat ), + .ak ( vidak ), + .rq ( vidrq_int ), + + .busy ( vid_load ), + .stall ( ~hsync ), + + .dev_data ( pix_data ), + .dev_ak ( pix_ack ) + +); + +// this module does the math for a DMA channel +vidc_dmachannel #(.FIFO_SIZE(2)) CURSORDMA ( + + .rst ( flybk | rst_i ), + .clkcpu ( clkcpu ), + .clkdev ( clkpix ), + .cedev ( cepix ), + + .cpu_data ( viddat ), + + .ak ( vidak ), + .rq ( currq_int ), + + .busy ( cur_load ), + .stall ( hsync | vid_load ), + + .dev_data ( csr_data ), + .dev_ak ( csr_ack ) + +); + +// this module does the math for a DMA channel +vidc_dmachannel SOUNDDMA ( + + .rst ( rst_i ), + .clkcpu ( clkcpu ), + .clkdev ( clkpix ), + .cedev ( cepix ), + + .cpu_data ( viddat ), + .ak ( sndak ), + .rq ( sndrq ), + + .busy ( snd_load ), + .stall ( 1'b0 ), + + .dev_data ( snd_sam_data ), + .dev_ak ( snd_sam_en ) + +); + +vidc_audio AUDIOMIXER( + + .cpu_clk ( clkcpu ), + .cpu_wr ( vidw ), + .cpu_data ( cpu_dat ), + + .aud_clk ( clkpix ), + .aud_ce ( cepix ), + .aud_rst ( rst_i ), + .aud_data ( snd_sam_data ), + .aud_en ( snd_sam_en ), + + .aud_right ( audio_r ), + .aud_left ( audio_l ) + + ); + +integer c; + +initial begin + + // clear the palette. + for (c = 0; c < 16; c = c + 1) begin + + vidc_palette[c] = 13'd0; + + end + + vidc_cr = 16'hFFF0; + + pix_shift_count = 3'd0; + pix_data_latch = 8'd0; + pix_load = 1'b0; + + csr_shift_count = 3'd0; + csr_data_latch = 8'd0; + csr_load_count = 'd0; + csr_load = 1'b0; + +end + +localparam VIDEO_PALETTE = 6'b00xxxx; +localparam VIDEO_CONTROL = 6'b111000; +localparam VIDEO_BORDER = 6'b010000; +localparam CURSOR_PALETTE = 6'b0100xx; + +// DMA interface control +// this is in the cpu clock domain. +always @(posedge clkcpu) begin + + // register write control. + if (vidw == 1'b1) begin + + casex (cpu_dat[31:26]) + + VIDEO_PALETTE: begin // palette registers. 00-3CH + + vidc_palette[cpu_dat[29:26]] <= cpu_dat[12:0]; + + end + + CURSOR_PALETTE: begin // cursor palette + if (cpu_dat[27:26] == 2'b00) begin + vidc_border <= cpu_dat[12:0]; + end else begin + cur_palette[cpu_dat[27:26]] <= cpu_dat[12:0]; + end + end + + VIDEO_CONTROL: begin // control register. + + vidc_cr <= cpu_dat[15:0]; + + end + + endcase + + end + +end + +// pixel clock domain logic. +// this simulates the DAC. +always @(posedge clkpix) begin + + if(cepix) begin + cur_enabled_r <= cur_enabled; + pix_load <= pix_ack; + csr_load <= csr_ack; + + enabled_d1 <= enabled; + enabled_d2 <= enabled_d1; + + if (flybk == 1'b1) begin + + pix_data_latch <= 8'd0; + + end + + if (hsync == 1'b0) begin + + pix_shift_count <= 3'b111; + csr_shift_count <= 3'b111; + csr_load_count <= 'd0; + + end else if (enabled == 1'b1) begin + + case ({vidc_cr[3:2]}) + 2'b00: begin + pix_data_latch <= {1'b0, pix_data_latch[7:1]}; + pix_shift_count <= pix_shift_count + 3'd1; + end + + 2'b01: begin + pix_data_latch <= {2'b00, pix_data_latch[7:2]}; + pix_shift_count <= pix_shift_count + 3'd2; + end + + 2'b10: begin + pix_data_latch <= {4'b00, pix_data_latch[7:4]}; + pix_shift_count <= pix_shift_count + 3'd4; + end + + default: begin + pix_data_latch <= 8'd0; + end + endcase + + end + + if (cur_enabled_r) begin + + csr_data_latch <= {2'b00, csr_data_latch[7:2]}; + csr_shift_count <= csr_shift_count + 3'd2; + + end + + if (pix_load == 1'b1) begin + + pix_data_latch <= pix_data; + + end + + if (csr_load) begin + + csr_load_count <= csr_load_count + 1'd1; + csr_data_latch <= csr_data; + + end + end +end + +// eqn is CE + DE + ABC + BCD (where {E,D} = {vidc_cr[3:2]} and {C,B,A} = pix_shift_count) +assign pix_ack = enabled & ((pix_shift_count[2] & vidc_cr[3]) | ( vidc_cr[2] & vidc_cr[3]) | (pix_shift_count[0] & pix_shift_count[1] & pix_shift_count[2]) | (pix_shift_count[1] & pix_shift_count[2] & vidc_cr[2])); +assign csr_ack = cur_enabled & (csr_shift_count[2] & csr_shift_count[0] ) & ~csr_load & ~csr_load_count[3]; + +// TODO: fix 8 bits per pixel colours. +wire [3:0] pix_lookup = vidc_cr[3:2] == 2'b00 ? {3'd0, pix_data_latch[0]} : + vidc_cr[3:2] == 2'b01 ? {2'd0, pix_data_latch[1:0]} : pix_data_latch[3:0]; + +wire [1:0] csr_lookup = csr_data_latch[1:0]; + +wire [12:0] vidc_colour = cur_enabled & (csr_lookup != 2'd0) ? cur_palette[csr_lookup] : + enabled_d2 ? vidc_palette[pix_lookup] : + border ? vidc_border : + 13'd0; + +// render a hicolour pixel if in hicolour mode, enabled and the cursor isnt being displayed. +wire hicolour = (vidc_cr[3:2] == 2'b11) & enabled_d2 & !(cur_enabled & (csr_lookup != 2'd0)); + +assign video_r[3] = hicolour ? pix_data_latch[4] : vidc_colour[3]; +assign video_r[2:0] = vidc_colour[2:0]; + +assign video_g[3:2] = hicolour ? pix_data_latch[6:5] : vidc_colour[7:6]; +assign video_g[1:0] = vidc_colour[5:4]; + +assign video_b[3] = hicolour ? pix_data_latch[7] : vidc_colour[11]; +assign video_b[2:0] = vidc_colour[10:8]; + +assign video_en = border; + +// this demux's the two dma channels that share the vidrq. +assign vidrq = hsync ? vidrq_int : ~vid_load & currq_int; + +endmodule diff --git a/vidc_audio.v b/vidc_audio.v new file mode 100644 index 0000000..6a74fc1 --- /dev/null +++ b/vidc_audio.v @@ -0,0 +1,148 @@ +`timescale 1ns / 1ps +/* vidc_audio.v + + Copyright (c) 2015, Stephen J. Leary + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the nor the + * names of its contributors may be used to endorse or promote products + * derived from this software 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 BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +module vidc_audio +( + + // cpu side - used to write registers + input cpu_clk, // cpu clock + input cpu_wr, // write to video register. + input [31:0] cpu_data, // data to write (data bus). + + // audio/data side of the bus + input aud_clk, + input aud_ce, + input aud_rst, + input [7:0] aud_data, + output reg aud_en, + + // actual audio out signal + output reg [15:0] aud_right, + output reg [15:0] aud_left + ); + +localparam SOUND_SAMFREQ = 4'b1100; +localparam SOUND_REGISTERS = 5'b01100; + +wire aud_1mhz_en; +reg [4:0] aud_1mhz_count; + +reg [2:0] channel; + +reg [2:0] vidc_sir[0:7]; +reg [8:0] vidc_sfr; +wire [2:0] vidc_mixer = vidc_sir[channel]; + +reg [15:0] mulaw_table[0:255]; + +// 1mhz pulse counter. +reg [7:0] aud_delay_count; + +initial begin + + // load the u-law table + $readmemh("vidc_mulaw.mif", mulaw_table); + + + channel = 3'd0; + + aud_delay_count = 8'b11111111; + aud_1mhz_count = 5'd0; + +end + + +always @(posedge cpu_clk) begin + + if (cpu_wr) begin + + if ({cpu_data[31:29],cpu_data[25:24]} == SOUND_REGISTERS) begin + + $display("Writing the stereo image registers: 0x%08x", cpu_data); + vidc_sir[{cpu_data[28:26]}] <= cpu_data[2:0]; + + end + + if (cpu_data[31:28] == SOUND_SAMFREQ) begin + + $display("VIDC SFR: %x", cpu_data[7:0]); + if (cpu_data[8]) begin + vidc_sfr <= cpu_data[8:0]; + end + end + + end + +end + +always @(posedge aud_clk) begin + + if(aud_ce) begin + aud_en <= 1'b0; + aud_1mhz_count <= aud_1mhz_count + 1'd1; + if (aud_rst) begin + + channel <= 3'd0; + + aud_delay_count <= 8'b11111111; + aud_1mhz_count <= 5'd0; + + end else if (aud_1mhz_en) begin + + aud_1mhz_count <= 5'd0; + aud_delay_count <= aud_delay_count - 1'd1; + + if (aud_delay_count == 8'd0) begin + + channel <= channel + 1'd1; + + if ((vidc_mixer[2] == 1'b0) | (channel[1:0] == 2'b00)) begin + + aud_left <= mulaw_table[aud_data]; + + end + + if (vidc_mixer[2] == 1'b1) begin + + aud_right <= mulaw_table[aud_data]; + + end + + aud_en <= 1'b1; + aud_delay_count <= vidc_sfr[7:0]; + + end + end + end +end + +// this is the trigger for the 1mhz enable pulse. +assign aud_1mhz_en = &aud_1mhz_count[3:2]; // 24 now we're using the 24mhz clock. + +endmodule diff --git a/vidc_dmachannel.v b/vidc_dmachannel.v new file mode 100644 index 0000000..849e116 --- /dev/null +++ b/vidc_dmachannel.v @@ -0,0 +1,148 @@ +`timescale 1ns / 1ps +/* vidc_dmachannel.v + + Copyright (c) 2012-2015, Stephen J. Leary + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the nor the + * names of its contributors may be used to endorse or promote products + * derived from this software 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 BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +module vidc_dmachannel +( + input clkcpu, + input clkdev, + input cedev, + + input rst, + + // dma bus + input ak, + output reg rq, + input [31:0] cpu_data, + + output busy, + input stall, // dont start another request with this high. + + // device bus + input dev_ak, + output [7:0] dev_data +); + +parameter FIFO_SIZE = 3; +localparam MEM_DEPTH = 2**FIFO_SIZE; +localparam WORD_WIDTH = FIFO_SIZE; +localparam BYTE_WIDTH = FIFO_SIZE + 2; +localparam HALF_FULL = 1<<(WORD_WIDTH-1); + +reg [1:0] dma_count = 2'd0; +reg load = 1'b0; +reg ak_r = 1'b0; + +// each channel has a fifo of a different size. +wire [WORD_WIDTH-1:0] wr_ptr; +wire [WORD_WIDTH-1:0] space; + +wire full; + +wire fifo_can_load; + +initial begin + + rq = 1'b0; + +end + +vidc_fifo #(.FIFO_SIZE(FIFO_SIZE)) VIDEO_FIFO( + + .rst ( rst ), + .wr_clk ( clkcpu ), + .rd_clk ( clkdev ), + .rd_ce ( cedev ), + .wr_en ( ak & load ), + .rd_en ( dev_ak ), + + .din ( cpu_data ), + .dout ( dev_data ), + + .wr_ptr ( wr_ptr ), + + .space ( space ), + .full ( full ) +); + +// DMA interface control +// this is in the cpu clock domain. +always @(posedge clkcpu) begin + + ak_r <= ak; + + if (rst == 1'b1) begin + + // do reset logic + dma_count <= 2'd0; + load <= 1'b0; + rq <= 1'b0; + + end else begin + + // if the load is in progress + if ((load == 1'b1) & (ak == 1'b1)) begin + + // are we done? + if (dma_count == 2'd3) begin + + load <= 1'b0; + + end + + // clear the request on the first ack. + // the dma action will continue until 4 words are read. + rq <= 1'b0; + + // count the ack pulses + dma_count <= dma_count + 2'd1; + + end else if (load == 1'b0) begin + + // possibly unnecessary? + dma_count <= 2'd0; + + end + + // if the fifo can load and its our slot then go. + if (fifo_can_load === 1'b1) begin + + load <= 1'b1; + rq <= 1'b1; + + end + + end + +end + +// TODO: replace 2'b00 with bits 4 and 5 of fifo control register for video fifo. +assign fifo_can_load = ~stall & ((space > 3'd4) | ((space == 'd0) & (full == 1'b0))) & (wr_ptr[1:0] == 2'b00); +assign busy = load; + +endmodule diff --git a/vidc_fifo.v b/vidc_fifo.v new file mode 100644 index 0000000..d2f2112 --- /dev/null +++ b/vidc_fifo.v @@ -0,0 +1,136 @@ +`timescale 1ns / 1ps +/* vidc_fifo.v + + Copyright (c) 2012-2014, Stephen J. Leary + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the nor the + * names of its contributors may be used to endorse or promote products + * derived from this software 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 BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +module vidc_fifo #( + parameter FIFO_SIZE = 3 +) +( + input rst, + input wr_clk, + input wr_en, + input[31:0] din, + + input rd_clk, + input rd_ce, + input rd_en, + output reg [7:0] dout, + + output reg [WORD_WIDTH-1:0] wr_ptr, + output reg [WORD_WIDTH-1:0] space, + output reg full, + output empty +); + +localparam MEM_DEPTH = 2**FIFO_SIZE; +localparam WORD_WIDTH = FIFO_SIZE; +localparam BYTE_WIDTH = FIFO_SIZE + 2; + +reg [31:0] data[0:MEM_DEPTH-1]; +reg [BYTE_WIDTH-1:0] rd_ptr; + +integer k; + +initial begin + + wr_ptr = 'd0; + rd_ptr = 'd0; + full = 1'b0; + dout = 8'd0; + + for (k = 0; k < MEM_DEPTH; k = k + 1) + begin + data[k] = 32'd0; + end + + $display("FIFO has %x", MEM_DEPTH); + +end + +reg [BYTE_WIDTH-1:0] rd_ptr_r; + +always @(posedge wr_clk) begin + + rd_ptr_r <= rd_ptr; + space <= {rd_ptr_r[BYTE_WIDTH-1:2]} - wr_ptr; + + if (rst) begin + + wr_ptr <= 'd0; + full <= 1'b0; + + end else begin + + if (wr_ptr != {rd_ptr_r[BYTE_WIDTH-1:2]}) begin + + full <= 1'b0; + + end + + if (wr_en == 1'b1) begin + + data[wr_ptr] <= din; + wr_ptr <= wr_ptr + 2'd1; + full <= (wr_ptr + 2'd1) == {rd_ptr_r[BYTE_WIDTH-1:2]}; + + end + + end + +end + +wire [7:0] q; + +always @(posedge rd_clk) begin + + if(rd_ce) begin + if (rst) begin + + rd_ptr <= 'd0; + dout <= 8'd0; + + end else if (rd_en) begin + + if (~empty) begin + rd_ptr <= rd_ptr + 1'd1; + dout <= q; + end else begin + dout <= 'd0; + end + end + end +end + +assign empty = !full & space == 'd0; + +// cross the clock domain. +assign q = (rd_ptr[1:0] == 2'b00) ? data[{rd_ptr[BYTE_WIDTH-1:2]}][7:0] : + (rd_ptr[1:0] == 2'b01) ? data[{rd_ptr[BYTE_WIDTH-1:2]}][15:8] : + (rd_ptr[1:0] == 2'b10) ? data[{rd_ptr[BYTE_WIDTH-1:2]}][23:16] : data[{rd_ptr[BYTE_WIDTH-1:2]}][31:24]; + +endmodule diff --git a/vidc_mulaw.mif b/vidc_mulaw.mif new file mode 100644 index 0000000..7e515e1 --- /dev/null +++ b/vidc_mulaw.mif @@ -0,0 +1,256 @@ +8000 +8000 +8008 +7ff8 +8010 +7ff0 +8018 +7fe8 +8020 +7fe0 +8028 +7fd8 +8030 +7fd0 +8038 +7fc8 +8040 +7fc0 +8048 +7fb8 +8050 +7fb0 +8058 +7fa8 +8060 +7fa0 +8068 +7f98 +8070 +7f90 +8078 +7f88 +8084 +7f7c +8094 +7f6c +80a4 +7f5c +80b4 +7f4c +80c4 +7f3c +80d4 +7f2c +80e4 +7f1c +80f4 +7f0c +8104 +7efc +8114 +7eec +8124 +7edc +8134 +7ecc +8144 +7ebc +8154 +7eac +8164 +7e9c +8174 +7e8c +818c +7e74 +81ad +7e53 +81ce +7e32 +81ef +7e11 +8210 +7df0 +8231 +7dcf +8252 +7dae +8273 +7d8d +8294 +7d6c +82b5 +7d4b +82d6 +7d2a +82f7 +7d09 +8318 +7ce8 +8339 +7cc7 +835a +7ca6 +837b +7c85 +839c +7c64 +83de +7c22 +8420 +7be0 +8462 +7b9e +84a4 +7b5c +84e6 +7b1a +8528 +7ad8 +856a +7a96 +85ac +7a54 +85ee +7a12 +8630 +79d0 +8672 +798e +86b4 +794c +86f6 +790a +8738 +78c8 +877a +7886 +87bc +7844 +8840 +77c0 +88c4 +773c +8948 +76b8 +89cc +7634 +8a50 +75b0 +8ad4 +752c +8b58 +74a8 +8bdc +7424 +8c60 +73a0 +8ce4 +731c +8d68 +7298 +8dec +7214 +8e70 +7190 +8ef4 +710c +8f78 +7088 +8ffc +7004 +9104 +6efc +920c +6df4 +9314 +6cec +941c +6be4 +9524 +6adc +962c +69d4 +9734 +68cc +983c +67c4 +9944 +66bc +9a4c +65b4 +9b54 +64ac +9c5c +63a4 +9d64 +629c +9e6c +6194 +9f74 +608c +a07c +5f84 +a28c +5d74 +a49c +5b64 +a6ac +5954 +a8bc +5744 +aacc +5534 +acdc +5324 +aeec +5114 +b0fc +4f04 +b30c +4cf4 +b51c +4ae4 +b72c +48d4 +b93c +46c4 +bb4c +44b4 +bd5c +42a4 +bf6c +4094 +c17c +3e84 +c59c +3a64 +c9bc +3644 +cddc +3224 +d1fc +2e04 +d61c +29e4 +da3c +25c4 +de5c +21a4 +e27c +1d84 +e69c +1964 +eabc +1544 +eedc +1124 +f2fc +0d04 +f71c +08e4 +fb3c +04c4 +ff5c +00a4 diff --git a/vidc_timing.v b/vidc_timing.v new file mode 100644 index 0000000..cb3c8ff --- /dev/null +++ b/vidc_timing.v @@ -0,0 +1,187 @@ +`timescale 1ns / 1ps +/* vidc_timing.v + + Copyright (c) 2012-2014, Stephen J. Leary + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the nor the + * names of its contributors may be used to endorse or promote products + * derived from this software 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 BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +module vidc_timing( + + input clkcpu, // cpu clock + input wr, // write to video register. + input [31:0] cpu_dat, // data to write (data bus). + + input clkvid, + input cevid, + input rst, + + output reg o_vsync, + output reg o_hsync, + + output reg o_cursor, + output reg o_enabled, + output reg o_border, + output reg o_flyback /* synthesis keep */ + ); + +reg [9:0] hcount; +reg [9:0] vcount; + +// register locations +localparam VIDEO_HCR = 6'b100000; +localparam VIDEO_HSWR = 6'b100001; +localparam VIDEO_HBSR = 6'b100010; +localparam VIDEO_HDSR = 6'b100011; +localparam VIDEO_HDER = 6'b100100; +localparam VIDEO_HBER = 6'b100101; + +localparam VIDEO_VCR = 6'b101000; +localparam VIDEO_VSWR = 6'b101001; +localparam VIDEO_VBSR = 6'b101010; +localparam VIDEO_VDSR = 6'b101011; +localparam VIDEO_VDER = 6'b101100; +localparam VIDEO_VBER = 6'b101101; + +localparam VIDEO_VCSR = 6'b101110; +localparam VIDEO_VCER = 6'b101111; +localparam VIDEO_HCSR = 6'b100110; + +// vertical registers +reg [9:0] vidc_vcr; // vertical cycle register +reg [9:0] vidc_vswr; // vertical sync width +reg [9:0] vidc_vbsr; // vertical border start +reg [9:0] vidc_vdsr; // vertical display start +reg [9:0] vidc_vder; // vertical display end +reg [9:0] vidc_vber; // vertical border end + +// horizontal registers +reg [9:0] vidc_hcr; // horizontal cycle register +reg [9:0] vidc_hswr; // horizontal sync width +reg [9:0] vidc_hbsr; // horizontal border start +reg [9:0] vidc_hdsr; // horizontal display start +reg [9:0] vidc_hder; // horizontal display end +reg [9:0] vidc_hber; // horizontal border end + +// cursor registers +reg [10:0] vidc_hcsr; // horizontal cursor start +reg [10:0] vidc_hcer; // horizontal cursor start +reg [9:0] vidc_vcsr; // vertical cursor start +reg [9:0] vidc_vcer; // vertical cursor end + +initial begin + o_flyback = 0; + o_cursor = 0; + + hcount = 0; + vcount = 0; + + vidc_vcr = 0; // vertical cycle register + vidc_vswr = 0; // vertical sync width + vidc_vbsr = 0; // vertical border start + vidc_vdsr = 0; // vertical display start + vidc_vder = 0; // vertical display end + vidc_vber = 0; // vertical border end + + vidc_hcr = 0; // horizontal cycle register + vidc_hswr = 0; // horizontal sync width + vidc_hbsr = 0; // horizontal border start + vidc_hdsr = 0; // horizontal display start + vidc_hder = 0; // horizontal display end + vidc_hber = 0; // horizontal border end + + vidc_hcsr = 0; // horizontal cursor start + vidc_hcer = 0; // horizontal cursor end + vidc_vcsr = 0; // vertical cursor start + vidc_vcer = 0; // vertical cursor end +end + +always @(posedge clkcpu) begin + if (wr) begin + $display("Writing the timing registers: 0x%08x", cpu_dat); + case (cpu_dat[31:26]) + + // verical timing + VIDEO_VCR: vidc_vcr <= cpu_dat[23:14]; + VIDEO_VSWR: vidc_vswr <= cpu_dat[23:14]; + VIDEO_VBSR: vidc_vbsr <= cpu_dat[23:14]; + VIDEO_VBER: vidc_vber <= cpu_dat[23:14]; + VIDEO_VDSR: vidc_vdsr <= cpu_dat[23:14]; + VIDEO_VDER: vidc_vder <= cpu_dat[23:14]; + + // horizontal timing + VIDEO_HCR: vidc_hcr <= {cpu_dat[22:14], 1'b0}; + VIDEO_HSWR: vidc_hswr <= {cpu_dat[22:14], 1'b0}; + VIDEO_HBSR: vidc_hbsr <= {cpu_dat[22:14], 1'b0}; + VIDEO_HBER: vidc_hber <= {cpu_dat[22:14], 1'b0}; + VIDEO_HDSR: vidc_hdsr <= {cpu_dat[22:14], 1'b0}; + VIDEO_HDER: vidc_hder <= {cpu_dat[22:14], 1'b0}; + + VIDEO_HCSR: vidc_hcsr <= cpu_dat[23:13]; + + VIDEO_VCSR: vidc_vcsr <= cpu_dat[23:14]; + VIDEO_VCER: vidc_vcer <= cpu_dat[23:14]; + + default: vidc_vcr <= vidc_vcr; + endcase + end +end + +wire vborder = (vcount >= vidc_vbsr) & (vcount < vidc_vber); +wire hborder = (hcount >= vidc_hbsr) & (hcount < vidc_hber); +wire vdisplay = (vcount >= vidc_vdsr) & (vcount < vidc_vder); +wire hdisplay = (hcount >= vidc_hdsr) & (hcount < vidc_hder); +wire vflyback = (vcount >= vidc_vber); +wire vcursor = (vcount >= vidc_vcsr) & (vcount < vidc_vcer); +wire hcursor = ({1'b0, hcount} >= vidc_hcsr); + +always @(posedge clkvid) begin + + if(cevid) begin + o_flyback <= vflyback; + o_enabled <= hdisplay && vdisplay; + o_border <= hborder && vborder; + o_vsync <= ~((vcount <= vidc_vswr) & !rst); + o_hsync <= ~((hcount < vidc_hswr) & !rst); + + o_cursor <= hcursor & vcursor; + + // video frame control + if (hcount < vidc_hcr) begin + hcount <= hcount + 1'd1; + end else begin + // horizontal refresh time. + hcount <= 0; + if (vcount < vidc_vcr) begin + vcount <= vcount + 1'd1; + end else begin + // vertical refresh time + vcount <= 0; + end + end + end +end + + +endmodule