From 51178d21e8d90e993bbcbd1920e08388a183ccc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikolas=20H=C3=A4m=C3=A4l=C3=A4inen?= Date: Wed, 14 Jan 2015 22:02:31 +0200 Subject: [PATCH 1/4] Project restructured to support multiple boards. DE2 and DE2-70 support added. --- .gitignore | 22 + Makefile => board/de2/Makefile | 2 +- de0_nano.tcl => board/de2/de2.tcl | 155 +++--- board/de2_70/Makefile | 23 + board/de2_70/de2_70.tcl | 204 ++++++++ vhdl/DRAM.vhd | 127 ++++- vhdl/MonZ80_template.vhd | 56 --- vhdl/RAM4K36.vhd | 67 +++ vhdl/RAM4K9.vhd | 184 +++++++ vhdl/T80_Pack.vhd | 4 +- vhdl/{ => board/de2}/SDRAM_Controller.vhd | 14 +- vhdl/{pll.vhd => board/de2/pll_de2.vhd} | 2 +- vhdl/board/de2_70/SDRAM_Controller.vhd | 473 ++++++++++++++++++ vhdl/board/de2_70/pll_de2_70.vhd | 429 ++++++++++++++++ .../de2_70/top_level_de2_70.vhd} | 0 15 files changed, 1611 insertions(+), 151 deletions(-) create mode 100644 .gitignore rename Makefile => board/de2/Makefile (94%) rename de0_nano.tcl => board/de2/de2.tcl (65%) create mode 100644 board/de2_70/Makefile create mode 100644 board/de2_70/de2_70.tcl delete mode 100644 vhdl/MonZ80_template.vhd create mode 100644 vhdl/RAM4K36.vhd create mode 100644 vhdl/RAM4K9.vhd rename vhdl/{ => board/de2}/SDRAM_Controller.vhd (98%) rename vhdl/{pll.vhd => board/de2/pll_de2.vhd} (99%) create mode 100644 vhdl/board/de2_70/SDRAM_Controller.vhd create mode 100644 vhdl/board/de2_70/pll_de2_70.vhd rename vhdl/{top_level.vhd => board/de2_70/top_level_de2_70.vhd} (100%) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..51042a7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,22 @@ +board/**/*.asm.* +board/**/*.done +board/**/*.eda.* +board/**/*.fit.* +board/**/*.flow.* +board/**/*.map.* +board/**/*.pin +board/**/*.pof +board/**/*.qpf +board/**/*.qsf +board/**/*.sof +board/**/*.psf +board/**/*.sta.* +board/**/incremental_db/ +board/**/simulation/ +db/ +greybox_tmp/ +incremental_db/ +pll.qip +simulation/ +**/**/*.bak + diff --git a/Makefile b/board/de2/Makefile similarity index 94% rename from Makefile rename to board/de2/Makefile index c2b2a69..ba67f7d 100644 --- a/Makefile +++ b/board/de2/Makefile @@ -1,4 +1,4 @@ -DESIGN_NAME = de0_nano +DESIGN_NAME = de2 QUARTUS_OPTIONS = diff --git a/de0_nano.tcl b/board/de2/de2.tcl similarity index 65% rename from de0_nano.tcl rename to board/de2/de2.tcl index 7b8108c..6687eba 100644 --- a/de0_nano.tcl +++ b/board/de2/de2.tcl @@ -13,7 +13,7 @@ # applicable agreement for further details. # Quartus II: Generate Tcl File for Project -# File: de0_nano.tcl +# File: de2.tcl # Generated on: Sat Sep 6 02:27:17 2014 # Load Quartus II Tcl Project package @@ -24,24 +24,24 @@ set make_assignments 1 # Check that the right project is open if {[is_project_open]} { - if {[string compare $quartus(project) "de0_nano"]} { - puts "Project de0_nano is not open" + if {[string compare $quartus(project) "de2"]} { + puts "Project de2 is not open" set make_assignments 0 } } else { # Only open if not already open - if {[project_exists de0_nano]} { - project_open -revision de0_nano de0_nano + if {[project_exists de2]} { + project_open -revision de2 de2 } else { - project_new -revision de0_nano de0_nano + project_new -revision de2 de2 } set need_to_close_project 1 } # Make assignments if {$make_assignments} { - set_global_assignment -name FAMILY "Cyclone IV E" - set_global_assignment -name DEVICE EP4CE22F17C6 + set_global_assignment -name FAMILY "Cyclone II" + set_global_assignment -name DEVICE EP2C35F672C6 set_global_assignment -name TOP_LEVEL_ENTITY top_level set_global_assignment -name ORIGINAL_QUARTUS_VERSION 13.1 set_global_assignment -name PROJECT_CREATION_TIME_DATE "19:30:55 AUGUST 28, 2014" @@ -56,121 +56,122 @@ if {$make_assignments} { 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 STRATIX_DEVICE_IO_STANDARD "2.5 V" - set_global_assignment -name VHDL_FILE vhdl/DRAM.vhd - set_global_assignment -name VHDL_FILE vhdl/SDRAM_Controller.vhd - set_global_assignment -name VHDL_FILE vhdl/gpio.vhd - set_global_assignment -name VHDL_FILE vhdl/T80.vhd - set_global_assignment -name VHDL_FILE vhdl/top_level.vhd - set_global_assignment -name VHDL_FILE vhdl/Z80cpu.vhd - set_global_assignment -name VHDL_FILE vhdl/T80_Pack.vhd - set_global_assignment -name VHDL_FILE vhdl/T80_ALU.vhd - set_global_assignment -name VHDL_FILE vhdl/T80_MCode.vhd - set_global_assignment -name VHDL_FILE vhdl/T80_Reg.vhd - set_global_assignment -name VHDL_FILE vhdl/T80se.vhd - set_global_assignment -name VHDL_FILE vhdl/MMU.vhd - set_global_assignment -name VHDL_FILE vhdl/MonZ80.vhd - set_global_assignment -name VHDL_FILE vhdl/SSRAM.vhd - set_global_assignment -name VHDL_FILE vhdl/uart_interface.vhd - set_global_assignment -name VHDL_FILE vhdl/fifo.vhd - set_global_assignment -name VHDL_FILE vhdl/uart.vhd - set_global_assignment -name VHDL_FILE vhdl/timer.vhd - set_global_assignment -name VHDL_FILE vhdl/pll.vhd - set_global_assignment -name VHDL_FILE vhdl/clkscale.vhd - set_location_assignment PIN_J15 -to rst_n_pad_i + set_global_assignment -name VHDL_FILE ../../vhdl/board/de2/SDRAM_Controller.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/DRAM.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/gpio.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/T80.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/board/de2/top_level_de2.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/Z80cpu.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/T80_Pack.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/T80_ALU.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/T80_MCode.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/T80_Reg.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/T80se.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/MMU.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/MonZ80.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/SSRAM.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/uart_interface.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/fifo.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/uart.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/timer.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/board/de2/pll_de2.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/clkscale.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/RAM4K36.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/RAM4K9.vhd + + set_location_assignment PIN_G26 -to rst_n_pad_i set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to rst_n_pad_i - set_location_assignment PIN_R8 -to sys_clk_pad_i + set_location_assignment PIN_N2 -to sys_clk_pad_i set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to sys_clk_pad_i - set_location_assignment PIN_F13 -to serial_rx + set_location_assignment PIN_C25 -to serial_rx set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to serial_rx - set_location_assignment PIN_T15 -to serial_tx + set_location_assignment PIN_B25 -to serial_tx set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to serial_tx - set_location_assignment PIN_A15 -to leds[0] + set_location_assignment PIN_AE23 -to leds[0] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to leds[0] - set_location_assignment PIN_A13 -to leds[1] + set_location_assignment PIN_AF23 -to leds[1] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to leds[1] - set_location_assignment PIN_B13 -to leds[2] + set_location_assignment PIN_AB21 -to leds[2] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to leds[2] - set_location_assignment PIN_A11 -to leds[3] + set_location_assignment PIN_AC22 -to leds[3] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to leds[3] - set_location_assignment PIN_D1 -to leds[4] + set_location_assignment PIN_AD22 -to leds[4] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to leds[4] - set_location_assignment PIN_P2 -to SDRAM_ADDR[0] + set_location_assignment PIN_T6 -to SDRAM_ADDR[0] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[0] - set_location_assignment PIN_N5 -to SDRAM_ADDR[1] + set_location_assignment PIN_V4 -to SDRAM_ADDR[1] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[1] - set_location_assignment PIN_N6 -to SDRAM_ADDR[2] + set_location_assignment PIN_V3 -to SDRAM_ADDR[2] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[2] - set_location_assignment PIN_M8 -to SDRAM_ADDR[3] + set_location_assignment PIN_W2 -to SDRAM_ADDR[3] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[3] - set_location_assignment PIN_P8 -to SDRAM_ADDR[4] + set_location_assignment PIN_W1 -to SDRAM_ADDR[4] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[4] - set_location_assignment PIN_T7 -to SDRAM_ADDR[5] + set_location_assignment PIN_U6 -to SDRAM_ADDR[5] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[5] - set_location_assignment PIN_N8 -to SDRAM_ADDR[6] + set_location_assignment PIN_U7 -to SDRAM_ADDR[6] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[6] - set_location_assignment PIN_T6 -to SDRAM_ADDR[7] + set_location_assignment PIN_U5 -to SDRAM_ADDR[7] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[7] - set_location_assignment PIN_R1 -to SDRAM_ADDR[8] + set_location_assignment PIN_W4 -to SDRAM_ADDR[8] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[8] - set_location_assignment PIN_P1 -to SDRAM_ADDR[9] + set_location_assignment PIN_W3 -to SDRAM_ADDR[9] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[9] - set_location_assignment PIN_N2 -to SDRAM_ADDR[10] + set_location_assignment PIN_Y1 -to SDRAM_ADDR[10] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[10] - set_location_assignment PIN_N1 -to SDRAM_ADDR[11] + set_location_assignment PIN_V5 -to SDRAM_ADDR[11] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[11] - set_location_assignment PIN_L4 -to SDRAM_ADDR[12] - set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[12] - set_location_assignment PIN_G2 -to SDRAM_DQ[0] + set_location_assignment PIN_V6 -to SDRAM_DQ[0] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[0] - set_location_assignment PIN_G1 -to SDRAM_DQ[1] + set_location_assignment PIN_AA2 -to SDRAM_DQ[1] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[1] - set_location_assignment PIN_L8 -to SDRAM_DQ[2] + set_location_assignment PIN_AA1 -to SDRAM_DQ[2] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[2] - set_location_assignment PIN_K5 -to SDRAM_DQ[3] + set_location_assignment PIN_Y3 -to SDRAM_DQ[3] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[3] - set_location_assignment PIN_K2 -to SDRAM_DQ[4] + set_location_assignment PIN_Y4 -to SDRAM_DQ[4] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[4] - set_location_assignment PIN_J2 -to SDRAM_DQ[5] + set_location_assignment PIN_R8 -to SDRAM_DQ[5] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[5] - set_location_assignment PIN_J1 -to SDRAM_DQ[6] + set_location_assignment PIN_T8 -to SDRAM_DQ[6] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[6] - set_location_assignment PIN_R7 -to SDRAM_DQ[7] + set_location_assignment PIN_V7 -to SDRAM_DQ[7] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[7] - set_location_assignment PIN_T4 -to SDRAM_DQ[8] + set_location_assignment PIN_W6 -to SDRAM_DQ[8] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[8] - set_location_assignment PIN_T2 -to SDRAM_DQ[9] + set_location_assignment PIN_AB2 -to SDRAM_DQ[9] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[9] - set_location_assignment PIN_T3 -to SDRAM_DQ[10] + set_location_assignment PIN_AB1 -to SDRAM_DQ[10] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[10] - set_location_assignment PIN_R3 -to SDRAM_DQ[11] + set_location_assignment PIN_AA4 -to SDRAM_DQ[11] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[11] - set_location_assignment PIN_R5 -to SDRAM_DQ[12] + set_location_assignment PIN_AA3 -to SDRAM_DQ[12] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[12] - set_location_assignment PIN_P3 -to SDRAM_DQ[13] + set_location_assignment PIN_AC2 -to SDRAM_DQ[13] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[13] - set_location_assignment PIN_N3 -to SDRAM_DQ[14] + set_location_assignment PIN_AC1 -to SDRAM_DQ[14] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[14] - set_location_assignment PIN_K1 -to SDRAM_DQ[15] + set_location_assignment PIN_AA5 -to SDRAM_DQ[15] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[15] - set_location_assignment PIN_R6 -to SDRAM_DQM[0] + set_location_assignment PIN_AD2 -to SDRAM_DQM[0] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQM[0] - set_location_assignment PIN_T5 -to SDRAM_DQM[1] + set_location_assignment PIN_Y5 -to SDRAM_DQM[1] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQM[1] - set_location_assignment PIN_M7 -to SDRAM_BA[0] + set_location_assignment PIN_AE2 -to SDRAM_BA[0] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_BA[0] - set_location_assignment PIN_M6 -to SDRAM_BA[1] + set_location_assignment PIN_AE3 -to SDRAM_BA[1] set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_BA[1] - set_location_assignment PIN_L1 -to SDRAM_nCAS + set_location_assignment PIN_AB3 -to SDRAM_nCAS set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_nCAS - set_location_assignment PIN_L7 -to SDRAM_CKE + set_location_assignment PIN_AA6 -to SDRAM_CKE set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_CKE - set_location_assignment PIN_P6 -to SDRAM_CS + set_location_assignment PIN_AC3 -to SDRAM_CS set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_CS - set_location_assignment PIN_L2 -to SDRAM_nRAS + set_location_assignment PIN_AB4 -to SDRAM_nRAS set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_nRAS - set_location_assignment PIN_C2 -to SDRAM_nWE + set_location_assignment PIN_AD3 -to SDRAM_nWE set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_nWE - set_location_assignment PIN_R4 -to SDRAM_CLK + set_location_assignment PIN_AA7 -to SDRAM_CLK set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_CLK set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to "DRAM:dram|SDRAM_Controller:sdram_ctrl|iob_command" set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to "DRAM:dram|SDRAM_Controller:sdram_ctrl|iob_address" diff --git a/board/de2_70/Makefile b/board/de2_70/Makefile new file mode 100644 index 0000000..c237e0b --- /dev/null +++ b/board/de2_70/Makefile @@ -0,0 +1,23 @@ +DESIGN_NAME = de2_70 +QUARTUS_OPTIONS = + + +all: asm + +project: $(TCL_FILE) + quartus_sh $(QUARTUS_OPTIONS) -t $(DESIGN_NAME).tcl + +map: project + quartus_map $(QUARTUS_OPTIONS) $(DESIGN_NAME) + +fit: map + quartus_fit $(QUARTUS_OPTIONS) $(DESIGN_NAME) + +asm: fit + quartus_asm $(QUARTUS_OPTIONS) $(DESIGN_NAME) + +sta: asm + quartus_sta $(QUARTUS_OPTIONS) $(DESIGN_NAME) + +load: asm + quartus_pgm --mode=jtag -o p\;$(DESIGN_NAME).sof diff --git a/board/de2_70/de2_70.tcl b/board/de2_70/de2_70.tcl new file mode 100644 index 0000000..a2db448 --- /dev/null +++ b/board/de2_70/de2_70.tcl @@ -0,0 +1,204 @@ +# Copyright (C) 1991-2013 Altera Corporation +# Your use of Altera 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 Altera Program License +# Subscription Agreement, Altera 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 Altera and sold by +# Altera or its authorized distributors. Please refer to the +# applicable agreement for further details. + +# Quartus II: Generate Tcl File for Project +# File: de2_70.tcl +# Generated on: Sat Sep 6 02:27:17 2014 + +# Load Quartus II Tcl Project package +package require ::quartus::project + +set need_to_close_project 0 +set make_assignments 1 + +# Check that the right project is open +if {[is_project_open]} { + if {[string compare $quartus(project) "de2_70"]} { + puts "Project de2_70 is not open" + set make_assignments 0 + } +} else { + # Only open if not already open + if {[project_exists de2_70]} { + project_open -revision de2_70 de2_70 + } else { + project_new -revision de2_70 de2_70 + } + set need_to_close_project 1 +} + +# Make assignments +if {$make_assignments} { + set_global_assignment -name FAMILY "Cyclone II" + set_global_assignment -name DEVICE EP2C70F896C6 + set_global_assignment -name TOP_LEVEL_ENTITY top_level + set_global_assignment -name ORIGINAL_QUARTUS_VERSION 13.1 + set_global_assignment -name PROJECT_CREATION_TIME_DATE "19:30:55 AUGUST 28, 2014" + set_global_assignment -name LAST_QUARTUS_VERSION 13.1 + set_global_assignment -name EDA_SIMULATION_TOOL "ModelSim-Altera (VHDL)" + set_global_assignment -name EDA_OUTPUT_DATA_FORMAT VHDL -section_id eda_simulation + 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 0 + set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85 + 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 STRATIX_DEVICE_IO_STANDARD "2.5 V" + set_global_assignment -name VHDL_FILE ../../vhdl/board/de2_70/SDRAM_Controller.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/DRAM.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/gpio.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/T80.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/board/de2_70/top_level_de2_70.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/Z80cpu.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/T80_Pack.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/T80_ALU.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/T80_MCode.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/T80_Reg.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/T80se.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/MMU.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/MonZ80.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/SSRAM.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/uart_interface.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/fifo.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/uart.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/timer.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/board/de2_70/pll_de2_70.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/clkscale.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/RAM4K36.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/RAM4K9.vhd + set_location_assignment PIN_T29 -to rst_n_pad_i + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to rst_n_pad_i + set_location_assignment PIN_AD15 -to sys_clk_pad_i + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to sys_clk_pad_i + set_location_assignment PIN_D21 -to serial_rx + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to serial_rx + set_location_assignment PIN_E21 -to serial_tx + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to serial_tx + set_location_assignment PIN_AJ6 -to leds[0] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to leds[0] + set_location_assignment PIN_AK5 -to leds[1] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to leds[1] + set_location_assignment PIN_AJ5 -to leds[2] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to leds[2] + set_location_assignment PIN_AJ4 -to leds[3] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to leds[3] + set_location_assignment PIN_AK3 -to leds[4] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to leds[4] + set_location_assignment PIN_AA4 -to SDRAM_ADDR[0] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[0] + set_location_assignment PIN_AA5 -to SDRAM_ADDR[1] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[1] + set_location_assignment PIN_AA6 -to SDRAM_ADDR[2] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[2] + set_location_assignment PIN_AB5 -to SDRAM_ADDR[3] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[3] + set_location_assignment PIN_AB7 -to SDRAM_ADDR[4] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[4] + set_location_assignment PIN_AC4 -to SDRAM_ADDR[5] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[5] + set_location_assignment PIN_AC5 -to SDRAM_ADDR[6] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[6] + set_location_assignment PIN_AC6 -to SDRAM_ADDR[7] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[7] + set_location_assignment PIN_AD4 -to SDRAM_ADDR[8] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[8] + set_location_assignment PIN_AC7 -to SDRAM_ADDR[9] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[9] + set_location_assignment PIN_Y8 -to SDRAM_ADDR[10] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[10] + set_location_assignment PIN_AE4 -to SDRAM_ADDR[11] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[11] + set_location_assignment PIN_AF4 -to SDRAM_ADDR[12] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[12] + set_location_assignment PIN_AC1 -to SDRAM_DQ[0] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[0] + set_location_assignment PIN_AC2 -to SDRAM_DQ[1] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[1] + set_location_assignment PIN_AC3 -to SDRAM_DQ[2] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[2] + set_location_assignment PIN_AD1 -to SDRAM_DQ[3] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[3] + set_location_assignment PIN_AD2 -to SDRAM_DQ[4] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[4] + set_location_assignment PIN_AD3 -to SDRAM_DQ[5] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[5] + set_location_assignment PIN_AE1 -to SDRAM_DQ[6] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[6] + set_location_assignment PIN_AE2 -to SDRAM_DQ[7] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[7] + set_location_assignment PIN_AE3 -to SDRAM_DQ[8] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[8] + set_location_assignment PIN_AF1 -to SDRAM_DQ[9] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[9] + set_location_assignment PIN_AF2 -to SDRAM_DQ[10] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[10] + set_location_assignment PIN_AF3 -to SDRAM_DQ[11] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[11] + set_location_assignment PIN_AG2 -to SDRAM_DQ[12] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[12] + set_location_assignment PIN_AG3 -to SDRAM_DQ[13] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[13] + set_location_assignment PIN_AH1 -to SDRAM_DQ[14] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[14] + set_location_assignment PIN_AH2 -to SDRAM_DQ[15] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[15] + set_location_assignment PIN_V9 -to SDRAM_DQM[0] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQM[0] + set_location_assignment PIN_AB6 -to SDRAM_DQM[1] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQM[1] + set_location_assignment PIN_AA9 -to SDRAM_BA[0] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_BA[0] + set_location_assignment PIN_AA10 -to SDRAM_BA[1] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_BA[1] + set_location_assignment PIN_W10 -to SDRAM_nCAS + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_nCAS + set_location_assignment PIN_AA8 -to SDRAM_CKE + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_CKE + set_location_assignment PIN_Y10 -to SDRAM_CS + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_CS + set_location_assignment PIN_Y9 -to SDRAM_nRAS + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_nRAS + set_location_assignment PIN_W9 -to SDRAM_nWE + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_nWE + set_location_assignment PIN_AD6 -to SDRAM_CLK + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_CLK + set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to "DRAM:dram|SDRAM_Controller:sdram_ctrl|iob_command" + set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to "DRAM:dram|SDRAM_Controller:sdram_ctrl|iob_address" + set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to "DRAM:dram|SDRAM_Controller:sdram_ctrl|iob_dqm" + set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to "DRAM:dram|SDRAM_Controller:sdram_ctrl|iob_cke" + set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to "DRAM:dram|SDRAM_Controller:sdram_ctrl|iob_bank" + set_instance_assignment -name FAST_INPUT_REGISTER ON -to "DRAM:dram|SDRAM_Controller:sdram_ctrl|iob_data" + set_instance_assignment -name FAST_INPUT_REGISTER ON -to "DRAM:dram|SDRAM_Controller:sdram_ctrl|captured_data" + set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_ADDR + set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_BA + set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_CKE + set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_CLK + set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_CS + set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQM + set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nCAS + set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nRAS + set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nWE + set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQ + set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ + set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top + + # Commit assignments + export_assignments + + # Close project + if {$need_to_close_project} { + project_close + } +} diff --git a/vhdl/DRAM.vhd b/vhdl/DRAM.vhd index c1750de..7f40589 100644 --- a/vhdl/DRAM.vhd +++ b/vhdl/DRAM.vhd @@ -112,13 +112,21 @@ architecture behaviour of DRAM is signal current_state : controller_state; signal next_state : controller_state; + -- here's the cache memory signals + signal cache_line_memory_write_enable : std_logic; + signal cache_line_memory_data_in : std_logic_vector(35 downto 0); -- 35 downto 32: validity bits; 31 downto 0: four data bytes + signal cache_line_memory_data_out : std_logic_vector(35 downto 0); + signal cache_tag_memory_write_enable : std_logic; + signal cache_tag_memory_data_in : std_logic_vector(8 downto 0); + signal cache_tag_memory_data_out : std_logic_vector(8 downto 0); + -- break up the incoming physical address alias address_byte : std_logic_vector(1 downto 0) is mem_address(1 downto 0); alias address_line : std_logic_vector(11 downto 0) is mem_address(13 downto 2); alias address_tag : std_logic_vector(8 downto 0) is mem_address(22 downto 14); alias address_word : std_logic_vector(20 downto 0) is mem_address(22 downto 2); -- mem_address(23) and mem_address(24) are unused in this design - + alias cache_inhibit : std_logic is mem_address(24); begin -- this should be based on the generic, really @@ -142,9 +150,14 @@ begin next_state <= st_idle; -- come back next cycle! else - cmd_enable <= '1'; - mem_wait <= '1'; - next_state <= st_read; + if cache_hit = '1' then + mem_wait <= '0'; + next_state <= st_read_done; + else + cmd_enable <= '1'; + mem_wait <= '1'; + next_state <= st_read; + end if; end if; elsif req_write = '1' then if word_changed = '1' then @@ -176,14 +189,14 @@ begin -- this kind of implies that they gave up on us? next_state <= st_idle; end if; - mem_wait <= (not sdram_data_out_ready); + mem_wait <= (not sdram_data_out_ready) and (not cache_hit); when st_read_done => if cs = '1' and req_read = '1' then next_state <= st_read_done; else next_state <= st_idle; end if; - mem_wait <= (not sdram_data_out_ready); + mem_wait <= (not sdram_data_out_ready) and (not cache_hit); when st_write => if cs = '1' and req_write = '1' then next_state <= st_write; @@ -203,6 +216,37 @@ begin end if; end process; + cache_address_check: process(cache_tag_memory_data_out, cache_line_memory_data_out, address_tag) + begin + if cache_tag_memory_data_out = address_tag then + address_hit <= '1'; + current_byte_valid <= cache_line_memory_data_out(35 downto 32); + else + address_hit <= '0'; + current_byte_valid <= "0000"; + end if; + end process; + + cache_byte_valid_check: process(address_byte, current_byte_valid) + begin + case address_byte is + when "00" => byte_valid_hit <= current_byte_valid(0); + when "01" => byte_valid_hit <= current_byte_valid(1); + when "10" => byte_valid_hit <= current_byte_valid(2); + when "11" => byte_valid_hit <= current_byte_valid(3); + when others => byte_valid_hit <= '0'; + end case; + end process; + + cache_hit_check: process(byte_valid_hit, address_hit, cache_inhibit) + begin + if address_hit = '1' and byte_valid_hit = '1' and cache_inhibit = '0' then + cache_hit <= '1'; + else + cache_hit <= '0'; + end if; + end process; + byte_enable_decode: process(address_byte) begin case address_byte is @@ -214,14 +258,14 @@ begin end case; end process; - data_out_demux: process(address_byte, sdram_data_out_ready, sdram_data_out, current_word) + data_out_demux: process(address_byte, sdram_data_out_ready, sdram_data_out, cache_line_memory_data_out, current_word) begin -- when the SDRAM is presenting data, feed it direct to the CPU. -- otherwise feed data from our cache memory. if sdram_data_out_ready = '1' then current_word <= sdram_data_out; else - current_word <= (others => '0'); + current_word <= cache_line_memory_data_out(31 downto 0); end if; case address_byte is @@ -233,6 +277,51 @@ begin end case; end process; + cache_write: process(current_state, data_in, next_state, write_back, cache_line_memory_data_out, sdram_data_out, sdram_data_out_ready, address_byte, current_byte_valid) + begin + if (next_state = st_read) or (write_back = '1') then + cache_tag_memory_write_enable <= '1'; + else + cache_tag_memory_write_enable <= '0'; + end if; + + cache_line_memory_write_enable <= '0'; + cache_line_memory_data_in <= cache_line_memory_data_out; + + if next_state = st_read then + cache_line_memory_data_in <= (others => '0'); -- set word and all valid flags to 1 + cache_line_memory_write_enable <= '1'; + end if; + + -- has our read completed? + if current_state = st_read then + if sdram_data_out_ready = '1' then + cache_line_memory_data_in <= "1111" & sdram_data_out; + cache_line_memory_write_enable <= '1'; + end if; + elsif write_back = '1' then + case address_byte is + when "00" => + cache_line_memory_data_in <= current_byte_valid(3 downto 1) & "1" & + cache_line_memory_data_out(31 downto 8) & data_in; + when "01" => + cache_line_memory_data_in <= + current_byte_valid(3 downto 2) & "1" & current_byte_valid(0) & + cache_line_memory_data_out(31 downto 16) & data_in & cache_line_memory_data_out(7 downto 0); + when "10" => + cache_line_memory_data_in <= + current_byte_valid(3) & "1" & current_byte_valid(1 downto 0) & + cache_line_memory_data_out(31 downto 24) & data_in & cache_line_memory_data_out(15 downto 0); + when "11" => + cache_line_memory_data_in <= + "1" & current_byte_valid(2 downto 0) & + data_in & cache_line_memory_data_out(23 downto 0); + when others => -- shut up, compiler! + end case; + cache_line_memory_write_enable <= '1'; + end if; + end process; + sdram_registers: process(clk) begin if rising_edge(clk) then @@ -279,4 +368,24 @@ begin SDRAM_DATA => SDRAM_DQ ); -end; + -- block RAM used to store cache line data and byte validity (packs nicely into 36 bits) + cacheline_memory_sram: entity work.RAM4K36 + port map ( + clk => clk, + write => cache_line_memory_write_enable, + address => address_line, + data_in => cache_line_memory_data_in, + data_out => cache_line_memory_data_out + + ); + + -- block RAM used to store cache line tag memory (packs nicely into 9 bits) + cachetag_memory_sram: entity work.RAM4K9 + port map ( + clock => clk, + wren => cache_tag_memory_write_enable, + address => address_line, + data => cache_tag_memory_data_in, + q => cache_tag_memory_data_out + ); + end; diff --git a/vhdl/MonZ80_template.vhd b/vhdl/MonZ80_template.vhd deleted file mode 100644 index c34c850..0000000 --- a/vhdl/MonZ80_template.vhd +++ /dev/null @@ -1,56 +0,0 @@ ---+-----------------------------------+-------------------------------------+-- ---| ___ ___ | (c) 2013-2014 William R Sowerbutts |-- ---| ___ ___ ___ ___( _ ) / _ \ | will@sowerbutts.com |-- ---| / __|/ _ \ / __|_ / _ \| | | | | |-- ---| \__ \ (_) | (__ / / (_) | |_| | | A Z80 FPGA computer, just for fun |-- ---| |___/\___/ \___/___\___/ \___/ | |-- ---| | http://sowerbutts.com/ |-- ---+-----------------------------------+-------------------------------------+-- ---| An inferrable 4KB ROM to contain the monitor program |-- ---+-------------------------------------------------------------------------+-- --- --- MonZ80_template.vhd contains the template VHDL for the ROM but no actual --- data. The "ROMHERE" string is replaced by byte data by the "make_vhdl_rom" --- tool in software/tools which is invoked to generate "MonZ80.vhd" after --- the monitor program has been assembled. - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -entity MonZ80 is - port( - clk : in std_logic; - a : in std_logic_vector(11 downto 0); - d : out std_logic_vector(7 downto 0) - ); -end MonZ80; - -architecture arch of MonZ80 is - constant byte_rom_WIDTH: integer := 8; - type byte_rom_type is array (0 to 4095) of std_logic_vector(byte_rom_WIDTH-1 downto 0); - signal address_latch : std_logic_vector(11 downto 0) := (others => '0'); - - -- actually memory cells - signal byte_rom : byte_rom_type := ( - -- ROM contents follows - - -%ROMHERE% - - - ); - -begin - - ram_process: process(clk, byte_rom) - begin - if rising_edge(clk) then - -- latch the address, in order to infer a synchronous memory - address_latch <= a; - end if; - end process; - - d <= byte_rom(to_integer(unsigned(address_latch))); - -end arch; diff --git a/vhdl/RAM4K36.vhd b/vhdl/RAM4K36.vhd new file mode 100644 index 0000000..0db864f --- /dev/null +++ b/vhdl/RAM4K36.vhd @@ -0,0 +1,67 @@ +--+-----------------------------------+-------------------------------------+-- +--| ___ ___ | (c) 2013-2014 William R Sowerbutts |-- +--| ___ ___ ___ ___( _ ) / _ \ | will@sowerbutts.com |-- +--| / __|/ _ \ / __|_ / _ \| | | | | |-- +--| \__ \ (_) | (__ / / (_) | |_| | | A Z80 FPGA computer, just for fun |-- +--| |___/\___/ \___/___\___/ \___/ | |-- +--| | http://sowerbutts.com/ |-- +--+-----------------------------------+-------------------------------------+-- +--| A 4096 entry deep, 36-bit wide RAM using four RAM4K9 devices (and thus |-- +--| eight Xilinx RAMB16BWER devices) |-- +--+-------------------------------------------------------------------------+-- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; +library UNISIM; +entity RAM4K36 is + port( + clk : in std_logic; + write : in std_logic; + address : in std_logic_vector(11 downto 0); + data_in : in std_logic_vector(35 downto 0); + data_out : out std_logic_vector(35 downto 0) + ); +end RAM4K36; + +architecture behaviour of RAM4K36 is + +begin + + ram0: entity work.RAM4K9 + port map ( + clock => clk, + wren => write, + address => address, + data => data_in(8 downto 0), + q => data_out(8 downto 0) + ); + + ram1: entity work.RAM4K9 + port map ( + clock => clk, + wren => write, + address => address, + data => data_in(17 downto 9), + q => data_out(17 downto 9) + ); + + ram2: entity work.RAM4K9 + port map ( + clock => clk, + wren => write, + address => address, + data => data_in(26 downto 18), + q => data_out(26 downto 18) + ); + + ram3: entity work.RAM4K9 + port map ( + clock => clk, + wren => write, + address => address, + data => data_in(35 downto 27), + q => data_out(35 downto 27) + ); + +end; diff --git a/vhdl/RAM4K9.vhd b/vhdl/RAM4K9.vhd new file mode 100644 index 0000000..ac5a065 --- /dev/null +++ b/vhdl/RAM4K9.vhd @@ -0,0 +1,184 @@ +-- megafunction wizard: %RAM: 1-PORT% +-- GENERATION: STANDARD +-- VERSION: WM1.0 +-- MODULE: altsyncram + +-- ============================================================ +-- File Name: ram4k9.vhd +-- Megafunction Name(s): +-- altsyncram +-- +-- Simulation Library Files(s): +-- altera_mf +-- ============================================================ +-- ************************************************************ +-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +-- +-- 11.0 Build 208 07/03/2011 SP 1 SJ Full Version +-- ************************************************************ + + +--Copyright (C) 1991-2011 Altera Corporation +--Your use of Altera 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 Altera Program License +--Subscription Agreement, Altera 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 Altera and sold by +--Altera or its authorized distributors. Please refer to the +--applicable agreement for further details. + + +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.all; + +ENTITY ram4k9 IS + PORT + ( + address : IN STD_LOGIC_VECTOR (11 DOWNTO 0); + clock : IN STD_LOGIC := '1'; + data : IN STD_LOGIC_VECTOR (8 DOWNTO 0); + wren : IN STD_LOGIC ; + q : OUT STD_LOGIC_VECTOR (8 DOWNTO 0) + ); +END ram4k9; + + +ARCHITECTURE SYN OF ram4k9 IS + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (8 DOWNTO 0); + + + + COMPONENT altsyncram + GENERIC ( + clock_enable_input_a : STRING; + clock_enable_output_a : STRING; + intended_device_family : STRING; + lpm_hint : STRING; + lpm_type : STRING; + numwords_a : NATURAL; + operation_mode : STRING; + outdata_aclr_a : STRING; + outdata_reg_a : STRING; + power_up_uninitialized : STRING; + ram_block_type : STRING; + widthad_a : NATURAL; + width_a : NATURAL; + width_byteena_a : NATURAL + ); + PORT ( + address_a : IN STD_LOGIC_VECTOR (11 DOWNTO 0); + clock0 : IN STD_LOGIC ; + data_a : IN STD_LOGIC_VECTOR (8 DOWNTO 0); + wren_a : IN STD_LOGIC ; + q_a : OUT STD_LOGIC_VECTOR (8 DOWNTO 0) + ); + END COMPONENT; + +BEGIN + q <= sub_wire0(8 DOWNTO 0); + + altsyncram_component : altsyncram + GENERIC MAP ( + clock_enable_input_a => "BYPASS", + clock_enable_output_a => "BYPASS", + intended_device_family => "Cyclone II", + lpm_hint => "ENABLE_RUNTIME_MOD=NO", + lpm_type => "altsyncram", + numwords_a => 4096, + operation_mode => "SINGLE_PORT", + outdata_aclr_a => "NONE", + outdata_reg_a => "UNREGISTERED", + power_up_uninitialized => "FALSE", + ram_block_type => "M4K", + widthad_a => 12, + width_a => 9, + width_byteena_a => 1 + ) + PORT MAP ( + address_a => address, + clock0 => clock, + data_a => data, + wren_a => wren, + q_a => sub_wire0 + ); + + + +END SYN; + +-- ============================================================ +-- CNX file retrieval info +-- ============================================================ +-- Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0" +-- Retrieval info: PRIVATE: AclrAddr NUMERIC "0" +-- Retrieval info: PRIVATE: AclrByte NUMERIC "0" +-- Retrieval info: PRIVATE: AclrData NUMERIC "0" +-- Retrieval info: PRIVATE: AclrOutput NUMERIC "0" +-- Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0" +-- Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "9" +-- Retrieval info: PRIVATE: BlankMemory NUMERIC "1" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0" +-- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0" +-- Retrieval info: PRIVATE: Clken NUMERIC "0" +-- Retrieval info: PRIVATE: DataBusSeparated NUMERIC "1" +-- Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0" +-- Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" +-- Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0" +-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone II" +-- Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0" +-- Retrieval info: PRIVATE: JTAG_ID STRING "NONE" +-- Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" +-- Retrieval info: PRIVATE: MIFfilename STRING "" +-- Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "4096" +-- Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "2" +-- Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_A NUMERIC "3" +-- Retrieval info: PRIVATE: RegAddr NUMERIC "1" +-- Retrieval info: PRIVATE: RegData NUMERIC "1" +-- Retrieval info: PRIVATE: RegOutput NUMERIC "0" +-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +-- Retrieval info: PRIVATE: SingleClock NUMERIC "1" +-- Retrieval info: PRIVATE: UseDQRAM NUMERIC "1" +-- Retrieval info: PRIVATE: WRCONTROL_ACLR_A NUMERIC "0" +-- Retrieval info: PRIVATE: WidthAddr NUMERIC "12" +-- Retrieval info: PRIVATE: WidthData NUMERIC "9" +-- Retrieval info: PRIVATE: rden NUMERIC "0" +-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +-- Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS" +-- Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS" +-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone II" +-- Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO" +-- Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +-- Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "4096" +-- Retrieval info: CONSTANT: OPERATION_MODE STRING "SINGLE_PORT" +-- Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" +-- Retrieval info: CONSTANT: OUTDATA_REG_A STRING "UNREGISTERED" +-- Retrieval info: CONSTANT: POWER_UP_UNINITIALIZED STRING "FALSE" +-- Retrieval info: CONSTANT: RAM_BLOCK_TYPE STRING "M4K" +-- Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "12" +-- Retrieval info: CONSTANT: WIDTH_A NUMERIC "9" +-- Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" +-- Retrieval info: USED_PORT: address 0 0 12 0 INPUT NODEFVAL "address[11..0]" +-- Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock" +-- Retrieval info: USED_PORT: data 0 0 9 0 INPUT NODEFVAL "data[8..0]" +-- Retrieval info: USED_PORT: q 0 0 9 0 OUTPUT NODEFVAL "q[8..0]" +-- Retrieval info: USED_PORT: wren 0 0 0 0 INPUT NODEFVAL "wren" +-- Retrieval info: CONNECT: @address_a 0 0 12 0 address 0 0 12 0 +-- Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0 +-- Retrieval info: CONNECT: @data_a 0 0 9 0 data 0 0 9 0 +-- Retrieval info: CONNECT: @wren_a 0 0 0 0 wren 0 0 0 0 +-- Retrieval info: CONNECT: q 0 0 9 0 @q_a 0 0 9 0 +-- Retrieval info: GEN_FILE: TYPE_NORMAL ram4k9.vhd TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL ram4k9.inc FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL ram4k9.cmp TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL ram4k9.bsf FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL ram4k9_inst.vhd FALSE +-- Retrieval info: LIB_FILE: altera_mf diff --git a/vhdl/T80_Pack.vhd b/vhdl/T80_Pack.vhd index 6904b66..9305475 100644 --- a/vhdl/T80_Pack.vhd +++ b/vhdl/T80_Pack.vhd @@ -59,7 +59,9 @@ library IEEE; use IEEE.std_logic_1164.all; package T80_Pack is - + constant T80_TAG_MEM: std_logic_vector(1 downto 0) := "01"; + constant T80_TAG_IO: std_logic_vector(1 downto 0) := "10"; + component T80 generic( Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB diff --git a/vhdl/SDRAM_Controller.vhd b/vhdl/board/de2/SDRAM_Controller.vhd similarity index 98% rename from vhdl/SDRAM_Controller.vhd rename to vhdl/board/de2/SDRAM_Controller.vhd index bbb5db7..6557ab0 100644 --- a/vhdl/SDRAM_Controller.vhd +++ b/vhdl/board/de2/SDRAM_Controller.vhd @@ -205,16 +205,18 @@ begin sdram_dqm <= iob_dqm; sdram_ba <= iob_bank; sdram_addr <= iob_address; + sdram_din <= sdram_data; + sdram_data <= iob_data when iob_dq_hiz = '0' else (others => 'Z'); --------------------------------------------------------------- -- Explicitly set up the tristate I/O buffers on the DQ signals --------------------------------------------------------------- -iob_dq_g: for i in 0 to 15 generate - begin -iob_dq_iob: altiobuf_bidir - generic map (number_of_channels => 1) - port map ( dataout(0) => sdram_din(i), dataio(0) => sdram_data(i), datain(0) => iob_data(i), oe(0) => iob_dq_hiz); -end generate; +--iob_dq_g: for i in 0 to 15 generate +-- begin +--iob_dq_iob: altiobuf_bidir +-- generic map (number_of_channels => 1) +-- port map ( dataout(0) => sdram_din(i), dataio(0) => sdram_data(i), datain(0) => iob_data(i), oe(0) => iob_dq_hiz); +--end generate; capture_proc: process(clk) begin diff --git a/vhdl/pll.vhd b/vhdl/board/de2/pll_de2.vhd similarity index 99% rename from vhdl/pll.vhd rename to vhdl/board/de2/pll_de2.vhd index 77ea317..c270ca1 100644 --- a/vhdl/pll.vhd +++ b/vhdl/board/de2/pll_de2.vhd @@ -170,7 +170,7 @@ BEGIN clk2_phase_shift => "0", compensate_clock => "CLK1", inclk0_input_frequency => 20000, - intended_device_family => "Cyclone IV E", + intended_device_family => "Cyclone II", lpm_hint => "CBX_MODULE_PREFIX=pll", lpm_type => "altpll", operation_mode => "NORMAL", diff --git a/vhdl/board/de2_70/SDRAM_Controller.vhd b/vhdl/board/de2_70/SDRAM_Controller.vhd new file mode 100644 index 0000000..919a0c1 --- /dev/null +++ b/vhdl/board/de2_70/SDRAM_Controller.vhd @@ -0,0 +1,473 @@ +---------------------------------------------------------------------------------- +-- Engineer: Mike Field +-- +-- Create Date: 14:09:12 09/15/2013 +-- Module Name: SDRAM_Controller - Behavioral +-- Description: Simple SDRAM controller for a Micron 48LC16M16A2-7E +-- or Micron 48LC4M16A2-7E @ 100MHz +-- Revision: +-- Revision 0.1 - Initial version +-- Revision 0.2 - Removed second clock signal that isn't needed. +-- Revision 0.3 - Added back-to-back reads and writes. +-- Revision 0.4 - Allow refeshes to be delayed till next PRECHARGE is issued, +-- Unless they get really, really delayed. If a delay occurs multiple +-- refreshes might get pushed out, but it will have avioded about +-- 50% of the refresh overhead +-- Revision 0.5 - Add more paramaters to the design, allowing it to work for both the +-- Papilio Pro and Logi-Pi +-- +-- Worst case performance (single accesses to different rows or banks) is: +-- Writes 16 cycles = 6,250,000 writes/sec = 25.0MB/s (excluding refresh overhead) +-- Reads 17 cycles = 5,882,352 reads/sec = 23.5MB/s (excluding refresh overhead) +-- +-- For 1:1 mixed reads and writes into the same row it is around 88MB/s +-- For reads or wries to the same it is can be as high as 184MB/s +---------------------------------------------------------------------------------- +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +library UNISIM; +use IEEE.NUMERIC_STD.ALL; +library altera_mf; +use altera_mf.altera_mf_components.all; + +entity SDRAM_Controller is + generic ( + sdram_address_width : natural; + sdram_column_bits : natural; + sdram_startup_cycles: natural; + cycles_per_refresh : natural + ); + Port ( clk : in STD_LOGIC; + reset : in STD_LOGIC; + + -- Interface to issue reads or write data + cmd_ready : out STD_LOGIC; -- '1' when a new command will be acted on + cmd_enable : in STD_LOGIC; -- Set to '1' to issue new command (only acted on when cmd_read = '1') + cmd_wr : in STD_LOGIC; -- Is this a write? + cmd_address : in STD_LOGIC_VECTOR(sdram_address_width-2 downto 0); -- address to read/write + cmd_byte_enable : in STD_LOGIC_VECTOR(3 downto 0); -- byte masks for the write command + cmd_data_in : in STD_LOGIC_VECTOR(31 downto 0); -- data for the write command + + data_out : out STD_LOGIC_VECTOR(31 downto 0); -- word read from SDRAM + data_out_ready : out STD_LOGIC; -- is new data ready? + + -- SDRAM signals + SDRAM_CLK : out STD_LOGIC; + SDRAM_CKE : out STD_LOGIC; + SDRAM_CS : out STD_LOGIC; + SDRAM_RAS : out STD_LOGIC; + SDRAM_CAS : out STD_LOGIC; + SDRAM_WE : out STD_LOGIC; + SDRAM_DQM : out STD_LOGIC_VECTOR( 1 downto 0); + SDRAM_ADDR : out STD_LOGIC_VECTOR(12 downto 0); + SDRAM_BA : out STD_LOGIC_VECTOR( 1 downto 0); + SDRAM_DATA : inout STD_LOGIC_VECTOR(15 downto 0)); +end SDRAM_Controller; + +architecture Behavioral of SDRAM_Controller is + -- From page 37 of MT48LC16M16A2 datasheet + -- Name (Function) CS# RAS# CAS# WE# DQM Addr Data + -- COMMAND INHIBIT (NOP) H X X X X X X + -- NO OPERATION (NOP) L H H H X X X + -- ACTIVE L L H H X Bank/row X + -- READ L H L H L/H Bank/col X + -- WRITE L H L L L/H Bank/col Valid + -- BURST TERMINATE L H H L X X Active + -- PRECHARGE L L H L X Code X + -- AUTO REFRESH L L L H X X X + -- LOAD MODE REGISTER L L L L X Op-code X + -- Write enable X X X X L X Active + -- Write inhibit X X X X H X High-Z + + -- Here are the commands mapped to constants + constant CMD_UNSELECTED : std_logic_vector(3 downto 0) := "1000"; + constant CMD_NOP : std_logic_vector(3 downto 0) := "0111"; + constant CMD_ACTIVE : std_logic_vector(3 downto 0) := "0011"; + constant CMD_READ : std_logic_vector(3 downto 0) := "0101"; + constant CMD_WRITE : std_logic_vector(3 downto 0) := "0100"; + constant CMD_TERMINATE : std_logic_vector(3 downto 0) := "0110"; + constant CMD_PRECHARGE : std_logic_vector(3 downto 0) := "0010"; + constant CMD_REFRESH : std_logic_vector(3 downto 0) := "0001"; + constant CMD_LOAD_MODE_REG : std_logic_vector(3 downto 0) := "0000"; + + constant MODE_REG : std_logic_vector(12 downto 0) := + -- Reserved, wr bust, OpMode, CAS Latency (2), Burst Type, Burst Length (2) + "000" & "0" & "00" & "010" & "0" & "001"; + + signal iob_command : std_logic_vector( 3 downto 0) := CMD_NOP; + signal iob_address : std_logic_vector(12 downto 0) := (others => '0'); + signal iob_data : std_logic_vector(15 downto 0) := (others => '0'); + signal iob_dqm : std_logic_vector( 1 downto 0) := (others => '0'); + signal iob_cke : std_logic := '0'; + signal iob_bank : std_logic_vector( 1 downto 0) := (others => '0'); + + attribute IOB: string; + attribute IOB of iob_command: signal is "true"; + attribute IOB of iob_address: signal is "true"; + attribute IOB of iob_dqm : signal is "true"; + attribute IOB of iob_cke : signal is "true"; + attribute IOB of iob_bank : signal is "true"; + attribute IOB of iob_data : signal is "true"; + + signal iob_data_next : std_logic_vector(15 downto 0) := (others => '0'); + signal captured_data : std_logic_vector(15 downto 0) := (others => '0'); + signal captured_data_last : std_logic_vector(15 downto 0) := (others => '0'); + signal sdram_din : std_logic_vector(15 downto 0); + attribute IOB of captured_data : signal is "true"; + + type fsm_state is (s_startup, + s_idle_in_6, s_idle_in_5, s_idle_in_4, s_idle_in_3, s_idle_in_2, s_idle_in_1, + s_idle, + s_open_in_2, s_open_in_1, + s_write_1, s_write_2, s_write_3, + s_read_1, s_read_2, s_read_3, s_read_4, + s_precharge + ); + + signal state : fsm_state := s_startup; + attribute FSM_ENCODING : string; + attribute FSM_ENCODING of state : signal is "ONE-HOT"; + + -- dual purpose counter, it counts up during the startup phase, then is used to trigger refreshes. + constant startup_refresh_max : unsigned(13 downto 0) := (others => '1'); + signal startup_refresh_count : unsigned(13 downto 0) := startup_refresh_max-to_unsigned(sdram_startup_cycles,14); + + -- logic to decide when to refresh + signal pending_refresh : std_logic := '0'; + signal forcing_refresh : std_logic := '0'; + + -- The incoming address is split into these three values + signal addr_row : std_logic_vector(12 downto 0) := (others => '0'); + signal addr_col : std_logic_vector(12 downto 0) := (others => '0'); + signal addr_bank : std_logic_vector( 1 downto 0) := (others => '0'); + + signal dqm_sr : std_logic_vector( 3 downto 0) := (others => '1'); -- an extra two bits in case CAS=3 + + -- signals to hold the requested transaction before it is completed + signal save_wr : std_logic := '0'; + signal save_row : std_logic_vector(12 downto 0); + signal save_bank : std_logic_vector( 1 downto 0); + signal save_col : std_logic_vector(12 downto 0); + signal save_data_in : std_logic_vector(31 downto 0); + signal save_byte_enable : std_logic_vector( 3 downto 0); + + -- control when new transactions are accepted + signal ready_for_new : std_logic := '0'; + signal got_transaction : std_logic := '0'; + + signal can_back_to_back : std_logic := '0'; + + -- signal to control the Hi-Z state of the DQ bus + signal iob_dq_hiz : std_logic := '1'; + + -- signals for when to read the data off of the bus + signal data_ready_delay : std_logic_vector( 4 downto 0); + + -- bit indexes used when splitting the address into row/colum/bank. + constant start_of_col : natural := 0; + constant end_of_col : natural := sdram_column_bits-2; + constant start_of_bank : natural := sdram_column_bits-1; + constant end_of_bank : natural := sdram_column_bits; + constant start_of_row : natural := sdram_column_bits+1; + constant end_of_row : natural := sdram_address_width-2; + constant prefresh_cmd : natural := 10; +begin + -- Indicate the need to refresh when the counter is 2048, + -- Force a refresh when the counter is 4096 - (if a refresh is forced, + -- multiple refresshes will be forced until the counter is below 2048 + pending_refresh <= startup_refresh_count(11); + forcing_refresh <= startup_refresh_count(12); + + -- tell the outside world when we can accept a new transaction; + cmd_ready <= ready_for_new; + ---------------------------------------------------------------------------- + -- Seperate the address into row / bank / address + ---------------------------------------------------------------------------- + addr_row(end_of_row-start_of_row downto 0) <= cmd_address(end_of_row downto start_of_row); -- 12:0 <= 22:10 + addr_bank <= cmd_address(end_of_bank downto start_of_bank); -- 1:0 <= 9:8 + addr_col(sdram_column_bits-1 downto 0) <= cmd_address(end_of_col downto start_of_col) & '0'; -- 8:0 <= 7:0 & '0' + --addr_row(12 downto 0) <= cmd_address(22 downto 10); -- 12:0 <= 22:10 + --addr_bank <= cmd_address( 9 downto 8); -- 1:0 <= 9:8 + --addr_col(8 downto 0) <= cmd_address( 7 downto 0) & '0'; -- 8:0 <= 7:0 & '0' + + ----------------------------------------------- + --!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + --!! Ensure that all outputs are registered. !! + --!! Check the pinout report to be sure !! + --!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + ----------------------------------------------- + sdram_cke <= iob_cke; + sdram_CS <= iob_command(3); + sdram_RAS <= iob_command(2); + sdram_CAS <= iob_command(1); + sdram_WE <= iob_command(0); + sdram_dqm <= iob_dqm; + sdram_ba <= iob_bank; + sdram_addr <= iob_address; + sdram_din <= sdram_data; + sdram_data <= iob_data when iob_dq_hiz = '0' else (others => 'Z'); + + --------------------------------------------------------------- + -- Explicitly set up the tristate I/O buffers on the DQ signals + --------------------------------------------------------------- +--iob_dq_g: for i in 0 to 15 generate +-- begin +--iob_dq_iob: altiobuf_bidir +-- generic map (number_of_channels => 1) +-- port map ( dataout(0) => sdram_din(i), dataio(0) => sdram_data(i), datain(0) => iob_data(i), oe(0) => iob_dq_hiz); +--end generate; + +capture_proc: process(clk) + begin + if rising_edge(clk) then + captured_data <= sdram_din; + end if; + end process; + +main_proc: process(clk) + begin + if rising_edge(clk) then + captured_data_last <= captured_data; + + ------------------------------------------------ + -- Default state is to do nothing + ------------------------------------------------ + iob_command <= CMD_NOP; + iob_address <= (others => '0'); + iob_bank <= (others => '0'); + + ------------------------------------------------ + -- countdown for initialisation & refresh + ------------------------------------------------ + startup_refresh_count <= startup_refresh_count+1; + + ------------------------------------------------------------------- + -- It we are ready for a new tranasction and one is being presented + -- then accept it. Also remember what we are reading or writing, + -- and if it can be back-to-backed with the last transaction + ------------------------------------------------------------------- + if ready_for_new = '1' and cmd_enable = '1' then + if save_bank = addr_bank and save_row = addr_row then + can_back_to_back <= '1'; + else + can_back_to_back <= '0'; + end if; + save_row <= addr_row; + save_bank <= addr_bank; + save_col <= addr_col; + save_wr <= cmd_wr; + save_data_in <= cmd_data_in; + save_byte_enable <= cmd_byte_enable; + got_transaction <= '1'; + ready_for_new <= '0'; + end if; + + ------------------------------------------------ + -- Handle the data coming back from the + -- SDRAM for the Read transaction + ------------------------------------------------ + data_out_ready <= '0'; + if data_ready_delay(0) = '1' then + data_out <= captured_data & captured_data_last; + data_out_ready <= '1'; + end if; + + ---------------------------------------------------------------------------- + -- update shift registers used to choose when to present data to/from memory + ---------------------------------------------------------------------------- + data_ready_delay <= '0' & data_ready_delay(data_ready_delay'high downto 1); + iob_dqm <= dqm_sr(1 downto 0); + dqm_sr <= "11" & dqm_sr(dqm_sr'high downto 2); + + case state is + when s_startup => + ------------------------------------------------------------------------ + -- 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 + ------------------------------------------------------------------------ + iob_CKE <= '1'; + + -- All the commands during the startup are NOPS, except these + if startup_refresh_count = startup_refresh_max-31 then + -- ensure all rows are closed + iob_command <= CMD_PRECHARGE; + iob_address(prefresh_cmd) <= '1'; -- all banks + iob_bank <= (others => '0'); + elsif startup_refresh_count = startup_refresh_max-23 then + -- these refreshes need to be at least tREF (66ns) apart + iob_command <= CMD_REFRESH; + elsif startup_refresh_count = startup_refresh_max-15 then + iob_command <= CMD_REFRESH; + elsif startup_refresh_count = startup_refresh_max-7 then + -- Now load the mode register + iob_command <= CMD_LOAD_MODE_REG; + iob_address <= MODE_REG; + end if; + + ------------------------------------------------------ + -- if startup is coomplete then go into idle mode, + -- get prepared to accept a new command, and schedule + -- the first refresh cycle + ------------------------------------------------------ + if startup_refresh_count = 0 then + state <= s_idle; + ready_for_new <= '1'; + got_transaction <= '0'; + startup_refresh_count <= to_unsigned(2048 - cycles_per_refresh+1,14); + end if; + + when s_idle_in_6 => state <= s_idle_in_5; + when s_idle_in_5 => state <= s_idle_in_4; + when s_idle_in_4 => state <= s_idle_in_3; + when s_idle_in_3 => state <= s_idle_in_2; + when s_idle_in_2 => state <= s_idle_in_1; + when s_idle_in_1 => state <= s_idle; + + when s_idle => + -- Priority is to issue a refresh if one is outstanding + if pending_refresh = '1' or forcing_refresh = '1' then + ------------------------------------------------------------------------ + -- Start the refresh cycle. + -- This tasks tRFC (66ns), so 6 idle cycles are needed @ 100MHz + ------------------------------------------------------------------------ + state <= s_idle_in_3; + iob_command <= CMD_REFRESH; + startup_refresh_count <= startup_refresh_count - cycles_per_refresh+1; + elsif got_transaction = '1' then + -------------------------------- + -- Start the read or write cycle. + -- First task is to open the row + -------------------------------- + state <= s_open_in_1; + iob_command <= CMD_ACTIVE; + iob_address <= save_row; + iob_bank <= save_bank; + end if; + + -------------------------------------------- + -- Opening the row ready for reads or writes + -------------------------------------------- + when s_open_in_2 => state <= s_open_in_1; + + when s_open_in_1 => + -- still waiting for row to open + if save_wr = '1' then + state <= s_write_1; + iob_dq_hiz <= '0'; + iob_data <= save_data_in(15 downto 0); -- get the DQ bus out of HiZ early + else + iob_dq_hiz <= '1'; + state <= s_read_1; + end if; + -- we will be ready for a new transaction next cycle! + ready_for_new <= '1'; + got_transaction <= '0'; + + ---------------------------------- + -- Processing the read transaction + ---------------------------------- + when s_read_1 => + state <= s_read_2; + iob_command <= CMD_READ; + iob_address <= save_col; + iob_bank <= save_bank; + iob_address(prefresh_cmd) <= '0'; -- A10 actually matters - it selects auto precharge + + -- Schedule reading the data values off the bus + data_ready_delay(data_ready_delay'high) <= '1'; + + -- Set the data masks to read all bytes + iob_dqm <= (others => '0'); + dqm_sr(1 downto 0) <= (others => '0'); + + when s_read_2 => + state <= s_read_3; + if forcing_refresh = '0' and got_transaction = '1' and can_back_to_back = '1' then + if save_wr = '0' then + state <= s_read_1; + ready_for_new <= '1'; -- we will be ready for a new transaction next cycle! + end if; + end if; + + when s_read_3 => + state <= s_read_4; + if forcing_refresh = '0' and got_transaction = '1' and can_back_to_back = '1' then + if save_wr = '0' then + state <= s_read_1; + ready_for_new <= '1'; -- we will be ready for a new transaction next cycle! + end if; + end if; + + when s_read_4 => + state <= s_precharge; + -- can we do back-to-back read? + if forcing_refresh = '0' and got_transaction = '1' and can_back_to_back = '1' then + if save_wr = '0' then + state <= s_read_1; + ready_for_new <= '1'; -- we will be ready for a new transaction next cycle! + else + state <= s_open_in_2; -- we have to wait for the read data to come back before we swutch the bus into HiZ + end if; + end if; + + ------------------------------------------------------------------ + -- Processing the write transaction + ------------------------------------------------------------------- + when s_write_1 => + state <= s_write_2; + iob_command <= CMD_WRITE; + iob_address <= save_col; + iob_address(prefresh_cmd) <= '0'; -- A10 actually matters - it selects auto precharge + iob_bank <= save_bank; + iob_dqm <= NOT save_byte_enable(1 downto 0); + dqm_sr(1 downto 0) <= NOT save_byte_enable(3 downto 2); + iob_data <= save_data_in(15 downto 0); + iob_data_next <= save_data_in(31 downto 16); + + when s_write_2 => + state <= s_write_3; + iob_data <= iob_data_next; + + when s_write_3 => -- must wait tRDL, hence the extra idle state + iob_dq_hiz <= '1'; + state <= s_precharge; + + ------------------------------------------------------------------- + -- Closing the row off (this closes all banks) + ------------------------------------------------------------------- + when s_precharge => + state <= s_idle_in_3; + iob_command <= CMD_PRECHARGE; + iob_address(prefresh_cmd) <= '1'; -- A10 actually matters - it selects all banks or just one + + ------------------------------------------------------------------- + -- We should never get here, but if we do then reset the memory + ------------------------------------------------------------------- + when others => + state <= s_startup; + ready_for_new <= '0'; + startup_refresh_count <= startup_refresh_max-to_unsigned(sdram_startup_cycles,14); + end case; + + if reset = '1' then -- Sync reset + state <= s_startup; + ready_for_new <= '0'; + startup_refresh_count <= startup_refresh_max-to_unsigned(sdram_startup_cycles,14); + end if; + end if; + end process; +end Behavioral; diff --git a/vhdl/board/de2_70/pll_de2_70.vhd b/vhdl/board/de2_70/pll_de2_70.vhd new file mode 100644 index 0000000..c270ca1 --- /dev/null +++ b/vhdl/board/de2_70/pll_de2_70.vhd @@ -0,0 +1,429 @@ +-- megafunction wizard: %ALTPLL% +-- GENERATION: STANDARD +-- VERSION: WM1.0 +-- MODULE: altpll + +-- ============================================================ +-- File Name: pll.vhd +-- Megafunction Name(s): +-- altpll +-- +-- Simulation Library Files(s): +-- altera_mf +-- ============================================================ +-- ************************************************************ +-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +-- +-- 13.1.0 Build 162 10/23/2013 SJ Web Edition +-- ************************************************************ + + +--Copyright (C) 1991-2013 Altera Corporation +--Your use of Altera 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 Altera Program License +--Subscription Agreement, Altera 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 Altera and sold by +--Altera or its authorized distributors. Please refer to the +--applicable agreement for further details. + + +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.all; + +ENTITY pll IS + PORT + ( + areset : IN STD_LOGIC := '0'; + inclk0 : IN STD_LOGIC := '0'; + c0 : OUT STD_LOGIC ; + c1 : OUT STD_LOGIC ; + c2 : OUT STD_LOGIC ; + locked : OUT STD_LOGIC + ); +END pll; + + +ARCHITECTURE SYN OF pll IS + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (4 DOWNTO 0); + SIGNAL sub_wire1 : STD_LOGIC ; + SIGNAL sub_wire2 : STD_LOGIC ; + SIGNAL sub_wire3 : STD_LOGIC ; + SIGNAL sub_wire4 : STD_LOGIC ; + SIGNAL sub_wire5 : STD_LOGIC ; + SIGNAL sub_wire6 : STD_LOGIC_VECTOR (1 DOWNTO 0); + SIGNAL sub_wire7_bv : BIT_VECTOR (0 DOWNTO 0); + SIGNAL sub_wire7 : STD_LOGIC_VECTOR (0 DOWNTO 0); + + + + COMPONENT altpll + GENERIC ( + bandwidth_type : STRING; + clk0_divide_by : NATURAL; + clk0_duty_cycle : NATURAL; + clk0_multiply_by : NATURAL; + clk0_phase_shift : STRING; + clk1_divide_by : NATURAL; + clk1_duty_cycle : NATURAL; + clk1_multiply_by : NATURAL; + clk1_phase_shift : STRING; + clk2_divide_by : NATURAL; + clk2_duty_cycle : NATURAL; + clk2_multiply_by : NATURAL; + clk2_phase_shift : STRING; + compensate_clock : STRING; + inclk0_input_frequency : NATURAL; + intended_device_family : STRING; + lpm_hint : STRING; + lpm_type : STRING; + operation_mode : STRING; + pll_type : STRING; + port_activeclock : STRING; + port_areset : STRING; + port_clkbad0 : STRING; + port_clkbad1 : STRING; + port_clkloss : STRING; + port_clkswitch : STRING; + port_configupdate : STRING; + port_fbin : STRING; + port_inclk0 : STRING; + port_inclk1 : STRING; + port_locked : STRING; + port_pfdena : STRING; + port_phasecounterselect : STRING; + port_phasedone : STRING; + port_phasestep : STRING; + port_phaseupdown : STRING; + port_pllena : STRING; + port_scanaclr : STRING; + port_scanclk : STRING; + port_scanclkena : STRING; + port_scandata : STRING; + port_scandataout : STRING; + port_scandone : STRING; + port_scanread : STRING; + port_scanwrite : STRING; + port_clk0 : STRING; + port_clk1 : STRING; + port_clk2 : STRING; + port_clk3 : STRING; + port_clk4 : STRING; + port_clk5 : STRING; + port_clkena0 : STRING; + port_clkena1 : STRING; + port_clkena2 : STRING; + port_clkena3 : STRING; + port_clkena4 : STRING; + port_clkena5 : STRING; + port_extclk0 : STRING; + port_extclk1 : STRING; + port_extclk2 : STRING; + port_extclk3 : STRING; + self_reset_on_loss_lock : STRING; + width_clock : NATURAL + ); + PORT ( + areset : IN STD_LOGIC ; + clk : OUT STD_LOGIC_VECTOR (4 DOWNTO 0); + inclk : IN STD_LOGIC_VECTOR (1 DOWNTO 0); + locked : OUT STD_LOGIC + ); + END COMPONENT; + +BEGIN + sub_wire7_bv(0 DOWNTO 0) <= "0"; + sub_wire7 <= To_stdlogicvector(sub_wire7_bv); + sub_wire4 <= sub_wire0(2); + sub_wire3 <= sub_wire0(0); + sub_wire1 <= sub_wire0(1); + c1 <= sub_wire1; + locked <= sub_wire2; + c0 <= sub_wire3; + c2 <= sub_wire4; + sub_wire5 <= inclk0; + sub_wire6 <= sub_wire7(0 DOWNTO 0) & sub_wire5; + + altpll_component : altpll + GENERIC MAP ( + bandwidth_type => "AUTO", + clk0_divide_by => 1, + clk0_duty_cycle => 50, + clk0_multiply_by => 1, + clk0_phase_shift => "-3000", + clk1_divide_by => 1, + clk1_duty_cycle => 50, + clk1_multiply_by => 1, + clk1_phase_shift => "0", + clk2_divide_by => 1, + clk2_duty_cycle => 50, + clk2_multiply_by => 2, + clk2_phase_shift => "0", + compensate_clock => "CLK1", + inclk0_input_frequency => 20000, + intended_device_family => "Cyclone II", + lpm_hint => "CBX_MODULE_PREFIX=pll", + lpm_type => "altpll", + operation_mode => "NORMAL", + pll_type => "AUTO", + port_activeclock => "PORT_UNUSED", + port_areset => "PORT_USED", + port_clkbad0 => "PORT_UNUSED", + port_clkbad1 => "PORT_UNUSED", + port_clkloss => "PORT_UNUSED", + port_clkswitch => "PORT_UNUSED", + port_configupdate => "PORT_UNUSED", + port_fbin => "PORT_UNUSED", + port_inclk0 => "PORT_USED", + port_inclk1 => "PORT_UNUSED", + port_locked => "PORT_USED", + port_pfdena => "PORT_UNUSED", + port_phasecounterselect => "PORT_UNUSED", + port_phasedone => "PORT_UNUSED", + port_phasestep => "PORT_UNUSED", + port_phaseupdown => "PORT_UNUSED", + port_pllena => "PORT_UNUSED", + port_scanaclr => "PORT_UNUSED", + port_scanclk => "PORT_UNUSED", + port_scanclkena => "PORT_UNUSED", + port_scandata => "PORT_UNUSED", + port_scandataout => "PORT_UNUSED", + port_scandone => "PORT_UNUSED", + port_scanread => "PORT_UNUSED", + port_scanwrite => "PORT_UNUSED", + port_clk0 => "PORT_USED", + port_clk1 => "PORT_USED", + port_clk2 => "PORT_USED", + port_clk3 => "PORT_UNUSED", + port_clk4 => "PORT_UNUSED", + port_clk5 => "PORT_UNUSED", + port_clkena0 => "PORT_UNUSED", + port_clkena1 => "PORT_UNUSED", + port_clkena2 => "PORT_UNUSED", + port_clkena3 => "PORT_UNUSED", + port_clkena4 => "PORT_UNUSED", + port_clkena5 => "PORT_UNUSED", + port_extclk0 => "PORT_UNUSED", + port_extclk1 => "PORT_UNUSED", + port_extclk2 => "PORT_UNUSED", + port_extclk3 => "PORT_UNUSED", + self_reset_on_loss_lock => "OFF", + width_clock => 5 + ) + PORT MAP ( + areset => areset, + inclk => sub_wire6, + clk => sub_wire0, + locked => sub_wire2 + ); + + + +END SYN; + +-- ============================================================ +-- CNX file retrieval info +-- ============================================================ +-- Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0" +-- Retrieval info: PRIVATE: BANDWIDTH STRING "1.000" +-- Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1" +-- Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz" +-- Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low" +-- Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1" +-- Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0" +-- Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0" +-- Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0" +-- Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0" +-- Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0" +-- Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0" +-- Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0" +-- Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c1" +-- Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0" +-- Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "Any" +-- Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "1" +-- Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "1" +-- Retrieval info: PRIVATE: DIV_FACTOR2 NUMERIC "1" +-- Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000" +-- Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000" +-- Retrieval info: PRIVATE: DUTY_CYCLE2 STRING "50.00000000" +-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "100.000000" +-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "100.000000" +-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE2 STRING "100.000000" +-- Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0" +-- Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0" +-- Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1" +-- Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0" +-- Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0" +-- Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575" +-- Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1" +-- Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "50.000" +-- Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz" +-- Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000" +-- Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1" +-- Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1" +-- Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz" +-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E" +-- Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1" +-- Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1" +-- Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1" +-- Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available" +-- Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0" +-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg" +-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "deg" +-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT2 STRING "ps" +-- Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any" +-- Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0" +-- Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0" +-- Retrieval info: PRIVATE: MIRROR_CLK2 STRING "0" +-- Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "2" +-- Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "2" +-- Retrieval info: PRIVATE: MULT_FACTOR2 NUMERIC "2" +-- Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1" +-- Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "90.00000000" +-- Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "100.00000000" +-- Retrieval info: PRIVATE: OUTPUT_FREQ2 STRING "100.00000000" +-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0" +-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "0" +-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE2 STRING "0" +-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz" +-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz" +-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT2 STRING "MHz" +-- Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1" +-- Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0" +-- Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "-54.00000000" +-- Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000" +-- Retrieval info: PRIVATE: PHASE_SHIFT2 STRING "0.00000000" +-- Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0" +-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg" +-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg" +-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT2 STRING "ps" +-- Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0" +-- Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "1" +-- Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1" +-- Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0" +-- Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0" +-- Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0" +-- Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0" +-- Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0" +-- Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0" +-- Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0" +-- Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll.mif" +-- Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0" +-- Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1" +-- Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0" +-- Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0" +-- Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0" +-- Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000" +-- Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz" +-- Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500" +-- Retrieval info: PRIVATE: SPREAD_USE STRING "0" +-- Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0" +-- Retrieval info: PRIVATE: STICKY_CLK0 STRING "1" +-- Retrieval info: PRIVATE: STICKY_CLK1 STRING "1" +-- Retrieval info: PRIVATE: STICKY_CLK2 STRING "1" +-- Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1" +-- Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1" +-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +-- Retrieval info: PRIVATE: USE_CLK0 STRING "1" +-- Retrieval info: PRIVATE: USE_CLK1 STRING "1" +-- Retrieval info: PRIVATE: USE_CLK2 STRING "1" +-- Retrieval info: PRIVATE: USE_CLKENA0 STRING "0" +-- Retrieval info: PRIVATE: USE_CLKENA1 STRING "0" +-- Retrieval info: PRIVATE: USE_CLKENA2 STRING "0" +-- Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0" +-- Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0" +-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +-- Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "AUTO" +-- Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "1" +-- Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" +-- Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "2" +-- Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "-1500" +-- Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "1" +-- Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50" +-- Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "2" +-- Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0" +-- Retrieval info: CONSTANT: CLK2_DIVIDE_BY NUMERIC "1" +-- Retrieval info: CONSTANT: CLK2_DUTY_CYCLE NUMERIC "50" +-- Retrieval info: CONSTANT: CLK2_MULTIPLY_BY NUMERIC "2" +-- Retrieval info: CONSTANT: CLK2_PHASE_SHIFT STRING "0" +-- Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK1" +-- Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "20000" +-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E" +-- Retrieval info: CONSTANT: LPM_TYPE STRING "altpll" +-- Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL" +-- Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO" +-- Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_USED" +-- Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED" +-- Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED" +-- Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED" +-- Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_USED" +-- Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_USED" +-- Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: SELF_RESET_ON_LOSS_LOCK STRING "OFF" +-- Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5" +-- Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]" +-- Retrieval info: USED_PORT: @inclk 0 0 2 0 INPUT_CLK_EXT VCC "@inclk[1..0]" +-- Retrieval info: USED_PORT: areset 0 0 0 0 INPUT GND "areset" +-- Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0" +-- Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1" +-- Retrieval info: USED_PORT: c2 0 0 0 0 OUTPUT_CLK_EXT VCC "c2" +-- Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0" +-- Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked" +-- Retrieval info: CONNECT: @areset 0 0 0 0 areset 0 0 0 0 +-- Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0 +-- Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0 +-- Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0 +-- Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1 +-- Retrieval info: CONNECT: c2 0 0 0 0 @clk 0 0 1 2 +-- Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0 +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll.vhd TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll.ppf TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll.inc FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll.cmp TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll.bsf FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll_inst.vhd FALSE +-- Retrieval info: LIB_FILE: altera_mf +-- Retrieval info: CBX_MODULE_PREFIX: ON diff --git a/vhdl/top_level.vhd b/vhdl/board/de2_70/top_level_de2_70.vhd similarity index 100% rename from vhdl/top_level.vhd rename to vhdl/board/de2_70/top_level_de2_70.vhd From c0368908b27ff673a2795684e0075167de096657 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikolas=20H=C3=A4m=C3=A4l=C3=A4inen?= Date: Wed, 14 Jan 2015 22:02:52 +0200 Subject: [PATCH 2/4] Project restructured to support multiple boards. DE2 and DE2-70 support added. --- board/de0_nano/Makefile | 23 + board/de0_nano/de0_nano.tcl | 204 +++++++++ vhdl/board/de0_nano/SDRAM_Controller.vhd | 472 +++++++++++++++++++++ vhdl/board/de0_nano/pll_de0_nano.vhd | 429 +++++++++++++++++++ vhdl/board/de0_nano/top_level_de0_nano.vhd | 465 ++++++++++++++++++++ vhdl/board/de2/top_level_de2.vhd | 466 ++++++++++++++++++++ 6 files changed, 2059 insertions(+) create mode 100644 board/de0_nano/Makefile create mode 100644 board/de0_nano/de0_nano.tcl create mode 100644 vhdl/board/de0_nano/SDRAM_Controller.vhd create mode 100644 vhdl/board/de0_nano/pll_de0_nano.vhd create mode 100644 vhdl/board/de0_nano/top_level_de0_nano.vhd create mode 100644 vhdl/board/de2/top_level_de2.vhd diff --git a/board/de0_nano/Makefile b/board/de0_nano/Makefile new file mode 100644 index 0000000..c2b2a69 --- /dev/null +++ b/board/de0_nano/Makefile @@ -0,0 +1,23 @@ +DESIGN_NAME = de0_nano +QUARTUS_OPTIONS = + + +all: asm + +project: $(TCL_FILE) + quartus_sh $(QUARTUS_OPTIONS) -t $(DESIGN_NAME).tcl + +map: project + quartus_map $(QUARTUS_OPTIONS) $(DESIGN_NAME) + +fit: map + quartus_fit $(QUARTUS_OPTIONS) $(DESIGN_NAME) + +asm: fit + quartus_asm $(QUARTUS_OPTIONS) $(DESIGN_NAME) + +sta: asm + quartus_sta $(QUARTUS_OPTIONS) $(DESIGN_NAME) + +load: asm + quartus_pgm --mode=jtag -o p\;$(DESIGN_NAME).sof diff --git a/board/de0_nano/de0_nano.tcl b/board/de0_nano/de0_nano.tcl new file mode 100644 index 0000000..6e9e367 --- /dev/null +++ b/board/de0_nano/de0_nano.tcl @@ -0,0 +1,204 @@ +# Copyright (C) 1991-2013 Altera Corporation +# Your use of Altera 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 Altera Program License +# Subscription Agreement, Altera 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 Altera and sold by +# Altera or its authorized distributors. Please refer to the +# applicable agreement for further details. + +# Quartus II: Generate Tcl File for Project +# File: de0_nano.tcl +# Generated on: Sat Sep 6 02:27:17 2014 + +# Load Quartus II Tcl Project package +package require ::quartus::project + +set need_to_close_project 0 +set make_assignments 1 + +# Check that the right project is open +if {[is_project_open]} { + if {[string compare $quartus(project) "de0_nano"]} { + puts "Project de0_nano is not open" + set make_assignments 0 + } +} else { + # Only open if not already open + if {[project_exists de0_nano]} { + project_open -revision de0_nano de0_nano + } else { + project_new -revision de0_nano de0_nano + } + set need_to_close_project 1 +} + +# Make assignments +if {$make_assignments} { + set_global_assignment -name FAMILY "Cyclone IV E" + set_global_assignment -name DEVICE EP4CE22F17C6 + set_global_assignment -name TOP_LEVEL_ENTITY top_level + set_global_assignment -name ORIGINAL_QUARTUS_VERSION 13.1 + set_global_assignment -name PROJECT_CREATION_TIME_DATE "19:30:55 AUGUST 28, 2014" + set_global_assignment -name LAST_QUARTUS_VERSION 13.1 + set_global_assignment -name EDA_SIMULATION_TOOL "ModelSim-Altera (VHDL)" + set_global_assignment -name EDA_OUTPUT_DATA_FORMAT VHDL -section_id eda_simulation + 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 0 + set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85 + 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 STRATIX_DEVICE_IO_STANDARD "2.5 V" + set_global_assignment -name VHDL_FILE ../../vhdl/board/de0_nano/SDRAM_Controller.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/DRAM.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/gpio.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/T80.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/board/de0_nano/top_level_de0_nano.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/Z80cpu.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/T80_Pack.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/T80_ALU.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/T80_MCode.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/T80_Reg.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/T80se.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/MMU.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/MonZ80.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/SSRAM.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/uart_interface.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/fifo.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/uart.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/timer.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/board/de0_nano/pll_de0_nano.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/clkscale.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/RAM4K36.vhd + set_global_assignment -name VHDL_FILE ../../vhdl/RAM4K9.vhd + set_location_assignment PIN_J15 -to rst_n_pad_i + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to rst_n_pad_i + set_location_assignment PIN_R8 -to sys_clk_pad_i + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to sys_clk_pad_i + set_location_assignment PIN_F13 -to serial_rx + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to serial_rx + set_location_assignment PIN_T15 -to serial_tx + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to serial_tx + set_location_assignment PIN_A15 -to leds[0] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to leds[0] + set_location_assignment PIN_A13 -to leds[1] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to leds[1] + set_location_assignment PIN_B13 -to leds[2] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to leds[2] + set_location_assignment PIN_A11 -to leds[3] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to leds[3] + set_location_assignment PIN_D1 -to leds[4] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to leds[4] + set_location_assignment PIN_P2 -to SDRAM_ADDR[0] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[0] + set_location_assignment PIN_N5 -to SDRAM_ADDR[1] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[1] + set_location_assignment PIN_N6 -to SDRAM_ADDR[2] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[2] + set_location_assignment PIN_M8 -to SDRAM_ADDR[3] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[3] + set_location_assignment PIN_P8 -to SDRAM_ADDR[4] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[4] + set_location_assignment PIN_T7 -to SDRAM_ADDR[5] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[5] + set_location_assignment PIN_N8 -to SDRAM_ADDR[6] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[6] + set_location_assignment PIN_T6 -to SDRAM_ADDR[7] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[7] + set_location_assignment PIN_R1 -to SDRAM_ADDR[8] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[8] + set_location_assignment PIN_P1 -to SDRAM_ADDR[9] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[9] + set_location_assignment PIN_N2 -to SDRAM_ADDR[10] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[10] + set_location_assignment PIN_N1 -to SDRAM_ADDR[11] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[11] + set_location_assignment PIN_L4 -to SDRAM_ADDR[12] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[12] + set_location_assignment PIN_G2 -to SDRAM_DQ[0] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[0] + set_location_assignment PIN_G1 -to SDRAM_DQ[1] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[1] + set_location_assignment PIN_L8 -to SDRAM_DQ[2] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[2] + set_location_assignment PIN_K5 -to SDRAM_DQ[3] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[3] + set_location_assignment PIN_K2 -to SDRAM_DQ[4] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[4] + set_location_assignment PIN_J2 -to SDRAM_DQ[5] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[5] + set_location_assignment PIN_J1 -to SDRAM_DQ[6] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[6] + set_location_assignment PIN_R7 -to SDRAM_DQ[7] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[7] + set_location_assignment PIN_T4 -to SDRAM_DQ[8] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[8] + set_location_assignment PIN_T2 -to SDRAM_DQ[9] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[9] + set_location_assignment PIN_T3 -to SDRAM_DQ[10] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[10] + set_location_assignment PIN_R3 -to SDRAM_DQ[11] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[11] + set_location_assignment PIN_R5 -to SDRAM_DQ[12] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[12] + set_location_assignment PIN_P3 -to SDRAM_DQ[13] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[13] + set_location_assignment PIN_N3 -to SDRAM_DQ[14] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[14] + set_location_assignment PIN_K1 -to SDRAM_DQ[15] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[15] + set_location_assignment PIN_R6 -to SDRAM_DQM[0] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQM[0] + set_location_assignment PIN_T5 -to SDRAM_DQM[1] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQM[1] + set_location_assignment PIN_M7 -to SDRAM_BA[0] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_BA[0] + set_location_assignment PIN_M6 -to SDRAM_BA[1] + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_BA[1] + set_location_assignment PIN_L1 -to SDRAM_nCAS + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_nCAS + set_location_assignment PIN_L7 -to SDRAM_CKE + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_CKE + set_location_assignment PIN_P6 -to SDRAM_CS + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_CS + set_location_assignment PIN_L2 -to SDRAM_nRAS + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_nRAS + set_location_assignment PIN_C2 -to SDRAM_nWE + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_nWE + set_location_assignment PIN_R4 -to SDRAM_CLK + set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_CLK + set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to "DRAM:dram|SDRAM_Controller:sdram_ctrl|iob_command" + set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to "DRAM:dram|SDRAM_Controller:sdram_ctrl|iob_address" + set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to "DRAM:dram|SDRAM_Controller:sdram_ctrl|iob_dqm" + set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to "DRAM:dram|SDRAM_Controller:sdram_ctrl|iob_cke" + set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to "DRAM:dram|SDRAM_Controller:sdram_ctrl|iob_bank" + set_instance_assignment -name FAST_INPUT_REGISTER ON -to "DRAM:dram|SDRAM_Controller:sdram_ctrl|iob_data" + set_instance_assignment -name FAST_INPUT_REGISTER ON -to "DRAM:dram|SDRAM_Controller:sdram_ctrl|captured_data" + set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_ADDR + set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_BA + set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_CKE + set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_CLK + set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_CS + set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQM + set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nCAS + set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nRAS + set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_nWE + set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM_DQ + set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM_DQ + set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top + + # Commit assignments + export_assignments + + # Close project + if {$need_to_close_project} { + project_close + } +} diff --git a/vhdl/board/de0_nano/SDRAM_Controller.vhd b/vhdl/board/de0_nano/SDRAM_Controller.vhd new file mode 100644 index 0000000..bbb5db7 --- /dev/null +++ b/vhdl/board/de0_nano/SDRAM_Controller.vhd @@ -0,0 +1,472 @@ +---------------------------------------------------------------------------------- +-- Engineer: Mike Field +-- +-- Create Date: 14:09:12 09/15/2013 +-- Module Name: SDRAM_Controller - Behavioral +-- Description: Simple SDRAM controller for a Micron 48LC16M16A2-7E +-- or Micron 48LC4M16A2-7E @ 100MHz +-- Revision: +-- Revision 0.1 - Initial version +-- Revision 0.2 - Removed second clock signal that isn't needed. +-- Revision 0.3 - Added back-to-back reads and writes. +-- Revision 0.4 - Allow refeshes to be delayed till next PRECHARGE is issued, +-- Unless they get really, really delayed. If a delay occurs multiple +-- refreshes might get pushed out, but it will have avioded about +-- 50% of the refresh overhead +-- Revision 0.5 - Add more paramaters to the design, allowing it to work for both the +-- Papilio Pro and Logi-Pi +-- +-- Worst case performance (single accesses to different rows or banks) is: +-- Writes 16 cycles = 6,250,000 writes/sec = 25.0MB/s (excluding refresh overhead) +-- Reads 17 cycles = 5,882,352 reads/sec = 23.5MB/s (excluding refresh overhead) +-- +-- For 1:1 mixed reads and writes into the same row it is around 88MB/s +-- For reads or wries to the same it is can be as high as 184MB/s +---------------------------------------------------------------------------------- +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +library UNISIM; +use IEEE.NUMERIC_STD.ALL; +library altera_mf; +use altera_mf.altera_mf_components.all; + + +entity SDRAM_Controller is + generic ( + sdram_address_width : natural; + sdram_column_bits : natural; + sdram_startup_cycles: natural; + cycles_per_refresh : natural + ); + Port ( clk : in STD_LOGIC; + reset : in STD_LOGIC; + + -- Interface to issue reads or write data + cmd_ready : out STD_LOGIC; -- '1' when a new command will be acted on + cmd_enable : in STD_LOGIC; -- Set to '1' to issue new command (only acted on when cmd_read = '1') + cmd_wr : in STD_LOGIC; -- Is this a write? + cmd_address : in STD_LOGIC_VECTOR(sdram_address_width-2 downto 0); -- address to read/write + cmd_byte_enable : in STD_LOGIC_VECTOR(3 downto 0); -- byte masks for the write command + cmd_data_in : in STD_LOGIC_VECTOR(31 downto 0); -- data for the write command + + data_out : out STD_LOGIC_VECTOR(31 downto 0); -- word read from SDRAM + data_out_ready : out STD_LOGIC; -- is new data ready? + + -- SDRAM signals + SDRAM_CLK : out STD_LOGIC; + SDRAM_CKE : out STD_LOGIC; + SDRAM_CS : out STD_LOGIC; + SDRAM_RAS : out STD_LOGIC; + SDRAM_CAS : out STD_LOGIC; + SDRAM_WE : out STD_LOGIC; + SDRAM_DQM : out STD_LOGIC_VECTOR( 1 downto 0); + SDRAM_ADDR : out STD_LOGIC_VECTOR(12 downto 0); + SDRAM_BA : out STD_LOGIC_VECTOR( 1 downto 0); + SDRAM_DATA : inout STD_LOGIC_VECTOR(15 downto 0)); +end SDRAM_Controller; + +architecture Behavioral of SDRAM_Controller is + -- From page 37 of MT48LC16M16A2 datasheet + -- Name (Function) CS# RAS# CAS# WE# DQM Addr Data + -- COMMAND INHIBIT (NOP) H X X X X X X + -- NO OPERATION (NOP) L H H H X X X + -- ACTIVE L L H H X Bank/row X + -- READ L H L H L/H Bank/col X + -- WRITE L H L L L/H Bank/col Valid + -- BURST TERMINATE L H H L X X Active + -- PRECHARGE L L H L X Code X + -- AUTO REFRESH L L L H X X X + -- LOAD MODE REGISTER L L L L X Op-code X + -- Write enable X X X X L X Active + -- Write inhibit X X X X H X High-Z + + -- Here are the commands mapped to constants + constant CMD_UNSELECTED : std_logic_vector(3 downto 0) := "1000"; + constant CMD_NOP : std_logic_vector(3 downto 0) := "0111"; + constant CMD_ACTIVE : std_logic_vector(3 downto 0) := "0011"; + constant CMD_READ : std_logic_vector(3 downto 0) := "0101"; + constant CMD_WRITE : std_logic_vector(3 downto 0) := "0100"; + constant CMD_TERMINATE : std_logic_vector(3 downto 0) := "0110"; + constant CMD_PRECHARGE : std_logic_vector(3 downto 0) := "0010"; + constant CMD_REFRESH : std_logic_vector(3 downto 0) := "0001"; + constant CMD_LOAD_MODE_REG : std_logic_vector(3 downto 0) := "0000"; + + constant MODE_REG : std_logic_vector(12 downto 0) := + -- Reserved, wr bust, OpMode, CAS Latency (2), Burst Type, Burst Length (2) + "000" & "0" & "00" & "010" & "0" & "001"; + + signal iob_command : std_logic_vector( 3 downto 0) := CMD_NOP; + signal iob_address : std_logic_vector(12 downto 0) := (others => '0'); + signal iob_data : std_logic_vector(15 downto 0) := (others => '0'); + signal iob_dqm : std_logic_vector( 1 downto 0) := (others => '0'); + signal iob_cke : std_logic := '0'; + signal iob_bank : std_logic_vector( 1 downto 0) := (others => '0'); + + attribute IOB: string; + attribute IOB of iob_command: signal is "true"; + attribute IOB of iob_address: signal is "true"; + attribute IOB of iob_dqm : signal is "true"; + attribute IOB of iob_cke : signal is "true"; + attribute IOB of iob_bank : signal is "true"; + attribute IOB of iob_data : signal is "true"; + + signal iob_data_next : std_logic_vector(15 downto 0) := (others => '0'); + signal captured_data : std_logic_vector(15 downto 0) := (others => '0'); + signal captured_data_last : std_logic_vector(15 downto 0) := (others => '0'); + signal sdram_din : std_logic_vector(15 downto 0); + attribute IOB of captured_data : signal is "true"; + + type fsm_state is (s_startup, + s_idle_in_6, s_idle_in_5, s_idle_in_4, s_idle_in_3, s_idle_in_2, s_idle_in_1, + s_idle, + s_open_in_2, s_open_in_1, + s_write_1, s_write_2, s_write_3, + s_read_1, s_read_2, s_read_3, s_read_4, + s_precharge + ); + + signal state : fsm_state := s_startup; + attribute FSM_ENCODING : string; + attribute FSM_ENCODING of state : signal is "ONE-HOT"; + + -- dual purpose counter, it counts up during the startup phase, then is used to trigger refreshes. + constant startup_refresh_max : unsigned(13 downto 0) := (others => '1'); + signal startup_refresh_count : unsigned(13 downto 0) := startup_refresh_max-to_unsigned(sdram_startup_cycles,14); + + -- logic to decide when to refresh + signal pending_refresh : std_logic := '0'; + signal forcing_refresh : std_logic := '0'; + + -- The incoming address is split into these three values + signal addr_row : std_logic_vector(12 downto 0) := (others => '0'); + signal addr_col : std_logic_vector(12 downto 0) := (others => '0'); + signal addr_bank : std_logic_vector( 1 downto 0) := (others => '0'); + + signal dqm_sr : std_logic_vector( 3 downto 0) := (others => '1'); -- an extra two bits in case CAS=3 + + -- signals to hold the requested transaction before it is completed + signal save_wr : std_logic := '0'; + signal save_row : std_logic_vector(12 downto 0); + signal save_bank : std_logic_vector( 1 downto 0); + signal save_col : std_logic_vector(12 downto 0); + signal save_data_in : std_logic_vector(31 downto 0); + signal save_byte_enable : std_logic_vector( 3 downto 0); + + -- control when new transactions are accepted + signal ready_for_new : std_logic := '0'; + signal got_transaction : std_logic := '0'; + + signal can_back_to_back : std_logic := '0'; + + -- signal to control the Hi-Z state of the DQ bus + signal iob_dq_hiz : std_logic := '1'; + + -- signals for when to read the data off of the bus + signal data_ready_delay : std_logic_vector( 4 downto 0); + + -- bit indexes used when splitting the address into row/colum/bank. + constant start_of_col : natural := 0; + constant end_of_col : natural := sdram_column_bits-2; + constant start_of_bank : natural := sdram_column_bits-1; + constant end_of_bank : natural := sdram_column_bits; + constant start_of_row : natural := sdram_column_bits+1; + constant end_of_row : natural := sdram_address_width-2; + constant prefresh_cmd : natural := 10; +begin + -- Indicate the need to refresh when the counter is 2048, + -- Force a refresh when the counter is 4096 - (if a refresh is forced, + -- multiple refresshes will be forced until the counter is below 2048 + pending_refresh <= startup_refresh_count(11); + forcing_refresh <= startup_refresh_count(12); + + -- tell the outside world when we can accept a new transaction; + cmd_ready <= ready_for_new; + ---------------------------------------------------------------------------- + -- Seperate the address into row / bank / address + ---------------------------------------------------------------------------- + addr_row(end_of_row-start_of_row downto 0) <= cmd_address(end_of_row downto start_of_row); -- 12:0 <= 22:10 + addr_bank <= cmd_address(end_of_bank downto start_of_bank); -- 1:0 <= 9:8 + addr_col(sdram_column_bits-1 downto 0) <= cmd_address(end_of_col downto start_of_col) & '0'; -- 8:0 <= 7:0 & '0' + --addr_row(12 downto 0) <= cmd_address(22 downto 10); -- 12:0 <= 22:10 + --addr_bank <= cmd_address( 9 downto 8); -- 1:0 <= 9:8 + --addr_col(8 downto 0) <= cmd_address( 7 downto 0) & '0'; -- 8:0 <= 7:0 & '0' + + ----------------------------------------------- + --!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + --!! Ensure that all outputs are registered. !! + --!! Check the pinout report to be sure !! + --!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + ----------------------------------------------- + sdram_cke <= iob_cke; + sdram_CS <= iob_command(3); + sdram_RAS <= iob_command(2); + sdram_CAS <= iob_command(1); + sdram_WE <= iob_command(0); + sdram_dqm <= iob_dqm; + sdram_ba <= iob_bank; + sdram_addr <= iob_address; + + --------------------------------------------------------------- + -- Explicitly set up the tristate I/O buffers on the DQ signals + --------------------------------------------------------------- +iob_dq_g: for i in 0 to 15 generate + begin +iob_dq_iob: altiobuf_bidir + generic map (number_of_channels => 1) + port map ( dataout(0) => sdram_din(i), dataio(0) => sdram_data(i), datain(0) => iob_data(i), oe(0) => iob_dq_hiz); +end generate; + +capture_proc: process(clk) + begin + if rising_edge(clk) then + captured_data <= sdram_din; + end if; + end process; + +main_proc: process(clk) + begin + if rising_edge(clk) then + captured_data_last <= captured_data; + + ------------------------------------------------ + -- Default state is to do nothing + ------------------------------------------------ + iob_command <= CMD_NOP; + iob_address <= (others => '0'); + iob_bank <= (others => '0'); + + ------------------------------------------------ + -- countdown for initialisation & refresh + ------------------------------------------------ + startup_refresh_count <= startup_refresh_count+1; + + ------------------------------------------------------------------- + -- It we are ready for a new tranasction and one is being presented + -- then accept it. Also remember what we are reading or writing, + -- and if it can be back-to-backed with the last transaction + ------------------------------------------------------------------- + if ready_for_new = '1' and cmd_enable = '1' then + if save_bank = addr_bank and save_row = addr_row then + can_back_to_back <= '1'; + else + can_back_to_back <= '0'; + end if; + save_row <= addr_row; + save_bank <= addr_bank; + save_col <= addr_col; + save_wr <= cmd_wr; + save_data_in <= cmd_data_in; + save_byte_enable <= cmd_byte_enable; + got_transaction <= '1'; + ready_for_new <= '0'; + end if; + + ------------------------------------------------ + -- Handle the data coming back from the + -- SDRAM for the Read transaction + ------------------------------------------------ + data_out_ready <= '0'; + if data_ready_delay(0) = '1' then + data_out <= captured_data & captured_data_last; + data_out_ready <= '1'; + end if; + + ---------------------------------------------------------------------------- + -- update shift registers used to choose when to present data to/from memory + ---------------------------------------------------------------------------- + data_ready_delay <= '0' & data_ready_delay(data_ready_delay'high downto 1); + iob_dqm <= dqm_sr(1 downto 0); + dqm_sr <= "11" & dqm_sr(dqm_sr'high downto 2); + + case state is + when s_startup => + ------------------------------------------------------------------------ + -- 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 + ------------------------------------------------------------------------ + iob_CKE <= '1'; + + -- All the commands during the startup are NOPS, except these + if startup_refresh_count = startup_refresh_max-31 then + -- ensure all rows are closed + iob_command <= CMD_PRECHARGE; + iob_address(prefresh_cmd) <= '1'; -- all banks + iob_bank <= (others => '0'); + elsif startup_refresh_count = startup_refresh_max-23 then + -- these refreshes need to be at least tREF (66ns) apart + iob_command <= CMD_REFRESH; + elsif startup_refresh_count = startup_refresh_max-15 then + iob_command <= CMD_REFRESH; + elsif startup_refresh_count = startup_refresh_max-7 then + -- Now load the mode register + iob_command <= CMD_LOAD_MODE_REG; + iob_address <= MODE_REG; + end if; + + ------------------------------------------------------ + -- if startup is coomplete then go into idle mode, + -- get prepared to accept a new command, and schedule + -- the first refresh cycle + ------------------------------------------------------ + if startup_refresh_count = 0 then + state <= s_idle; + ready_for_new <= '1'; + got_transaction <= '0'; + startup_refresh_count <= to_unsigned(2048 - cycles_per_refresh+1,14); + end if; + + when s_idle_in_6 => state <= s_idle_in_5; + when s_idle_in_5 => state <= s_idle_in_4; + when s_idle_in_4 => state <= s_idle_in_3; + when s_idle_in_3 => state <= s_idle_in_2; + when s_idle_in_2 => state <= s_idle_in_1; + when s_idle_in_1 => state <= s_idle; + + when s_idle => + -- Priority is to issue a refresh if one is outstanding + if pending_refresh = '1' or forcing_refresh = '1' then + ------------------------------------------------------------------------ + -- Start the refresh cycle. + -- This tasks tRFC (66ns), so 6 idle cycles are needed @ 100MHz + ------------------------------------------------------------------------ + state <= s_idle_in_3; + iob_command <= CMD_REFRESH; + startup_refresh_count <= startup_refresh_count - cycles_per_refresh+1; + elsif got_transaction = '1' then + -------------------------------- + -- Start the read or write cycle. + -- First task is to open the row + -------------------------------- + state <= s_open_in_1; + iob_command <= CMD_ACTIVE; + iob_address <= save_row; + iob_bank <= save_bank; + end if; + + -------------------------------------------- + -- Opening the row ready for reads or writes + -------------------------------------------- + when s_open_in_2 => state <= s_open_in_1; + + when s_open_in_1 => + -- still waiting for row to open + if save_wr = '1' then + state <= s_write_1; + iob_dq_hiz <= '0'; + iob_data <= save_data_in(15 downto 0); -- get the DQ bus out of HiZ early + else + iob_dq_hiz <= '1'; + state <= s_read_1; + end if; + -- we will be ready for a new transaction next cycle! + ready_for_new <= '1'; + got_transaction <= '0'; + + ---------------------------------- + -- Processing the read transaction + ---------------------------------- + when s_read_1 => + state <= s_read_2; + iob_command <= CMD_READ; + iob_address <= save_col; + iob_bank <= save_bank; + iob_address(prefresh_cmd) <= '0'; -- A10 actually matters - it selects auto precharge + + -- Schedule reading the data values off the bus + data_ready_delay(data_ready_delay'high) <= '1'; + + -- Set the data masks to read all bytes + iob_dqm <= (others => '0'); + dqm_sr(1 downto 0) <= (others => '0'); + + when s_read_2 => + state <= s_read_3; + if forcing_refresh = '0' and got_transaction = '1' and can_back_to_back = '1' then + if save_wr = '0' then + state <= s_read_1; + ready_for_new <= '1'; -- we will be ready for a new transaction next cycle! + end if; + end if; + + when s_read_3 => + state <= s_read_4; + if forcing_refresh = '0' and got_transaction = '1' and can_back_to_back = '1' then + if save_wr = '0' then + state <= s_read_1; + ready_for_new <= '1'; -- we will be ready for a new transaction next cycle! + end if; + end if; + + when s_read_4 => + state <= s_precharge; + -- can we do back-to-back read? + if forcing_refresh = '0' and got_transaction = '1' and can_back_to_back = '1' then + if save_wr = '0' then + state <= s_read_1; + ready_for_new <= '1'; -- we will be ready for a new transaction next cycle! + else + state <= s_open_in_2; -- we have to wait for the read data to come back before we swutch the bus into HiZ + end if; + end if; + + ------------------------------------------------------------------ + -- Processing the write transaction + ------------------------------------------------------------------- + when s_write_1 => + state <= s_write_2; + iob_command <= CMD_WRITE; + iob_address <= save_col; + iob_address(prefresh_cmd) <= '0'; -- A10 actually matters - it selects auto precharge + iob_bank <= save_bank; + iob_dqm <= NOT save_byte_enable(1 downto 0); + dqm_sr(1 downto 0) <= NOT save_byte_enable(3 downto 2); + iob_data <= save_data_in(15 downto 0); + iob_data_next <= save_data_in(31 downto 16); + + when s_write_2 => + state <= s_write_3; + iob_data <= iob_data_next; + + when s_write_3 => -- must wait tRDL, hence the extra idle state + iob_dq_hiz <= '1'; + state <= s_precharge; + + ------------------------------------------------------------------- + -- Closing the row off (this closes all banks) + ------------------------------------------------------------------- + when s_precharge => + state <= s_idle_in_3; + iob_command <= CMD_PRECHARGE; + iob_address(prefresh_cmd) <= '1'; -- A10 actually matters - it selects all banks or just one + + ------------------------------------------------------------------- + -- We should never get here, but if we do then reset the memory + ------------------------------------------------------------------- + when others => + state <= s_startup; + ready_for_new <= '0'; + startup_refresh_count <= startup_refresh_max-to_unsigned(sdram_startup_cycles,14); + end case; + + if reset = '1' then -- Sync reset + state <= s_startup; + ready_for_new <= '0'; + startup_refresh_count <= startup_refresh_max-to_unsigned(sdram_startup_cycles,14); + end if; + end if; + end process; +end Behavioral; diff --git a/vhdl/board/de0_nano/pll_de0_nano.vhd b/vhdl/board/de0_nano/pll_de0_nano.vhd new file mode 100644 index 0000000..1926e5f --- /dev/null +++ b/vhdl/board/de0_nano/pll_de0_nano.vhd @@ -0,0 +1,429 @@ +-- megafunction wizard: %ALTPLL% +-- GENERATION: STANDARD +-- VERSION: WM1.0 +-- MODULE: altpll + +-- ============================================================ +-- File Name: pll.vhd +-- Megafunction Name(s): +-- altpll +-- +-- Simulation Library Files(s): +-- altera_mf +-- ============================================================ +-- ************************************************************ +-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +-- +-- 13.1.0 Build 162 10/23/2013 SJ Web Edition +-- ************************************************************ + + +--Copyright (C) 1991-2013 Altera Corporation +--Your use of Altera 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 Altera Program License +--Subscription Agreement, Altera 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 Altera and sold by +--Altera or its authorized distributors. Please refer to the +--applicable agreement for further details. + + +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +LIBRARY altera_mf; +USE altera_mf.all; + +ENTITY pll IS + PORT + ( + areset : IN STD_LOGIC := '0'; + inclk0 : IN STD_LOGIC := '0'; + c0 : OUT STD_LOGIC ; + c1 : OUT STD_LOGIC ; + c2 : OUT STD_LOGIC ; + locked : OUT STD_LOGIC + ); +END pll; + + +ARCHITECTURE SYN OF pll IS + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (4 DOWNTO 0); + SIGNAL sub_wire1 : STD_LOGIC ; + SIGNAL sub_wire2 : STD_LOGIC ; + SIGNAL sub_wire3 : STD_LOGIC ; + SIGNAL sub_wire4 : STD_LOGIC ; + SIGNAL sub_wire5 : STD_LOGIC ; + SIGNAL sub_wire6 : STD_LOGIC_VECTOR (1 DOWNTO 0); + SIGNAL sub_wire7_bv : BIT_VECTOR (0 DOWNTO 0); + SIGNAL sub_wire7 : STD_LOGIC_VECTOR (0 DOWNTO 0); + + + + COMPONENT altpll + GENERIC ( + bandwidth_type : STRING; + clk0_divide_by : NATURAL; + clk0_duty_cycle : NATURAL; + clk0_multiply_by : NATURAL; + clk0_phase_shift : STRING; + clk1_divide_by : NATURAL; + clk1_duty_cycle : NATURAL; + clk1_multiply_by : NATURAL; + clk1_phase_shift : STRING; + clk2_divide_by : NATURAL; + clk2_duty_cycle : NATURAL; + clk2_multiply_by : NATURAL; + clk2_phase_shift : STRING; + compensate_clock : STRING; + inclk0_input_frequency : NATURAL; + intended_device_family : STRING; + lpm_hint : STRING; + lpm_type : STRING; + operation_mode : STRING; + pll_type : STRING; + port_activeclock : STRING; + port_areset : STRING; + port_clkbad0 : STRING; + port_clkbad1 : STRING; + port_clkloss : STRING; + port_clkswitch : STRING; + port_configupdate : STRING; + port_fbin : STRING; + port_inclk0 : STRING; + port_inclk1 : STRING; + port_locked : STRING; + port_pfdena : STRING; + port_phasecounterselect : STRING; + port_phasedone : STRING; + port_phasestep : STRING; + port_phaseupdown : STRING; + port_pllena : STRING; + port_scanaclr : STRING; + port_scanclk : STRING; + port_scanclkena : STRING; + port_scandata : STRING; + port_scandataout : STRING; + port_scandone : STRING; + port_scanread : STRING; + port_scanwrite : STRING; + port_clk0 : STRING; + port_clk1 : STRING; + port_clk2 : STRING; + port_clk3 : STRING; + port_clk4 : STRING; + port_clk5 : STRING; + port_clkena0 : STRING; + port_clkena1 : STRING; + port_clkena2 : STRING; + port_clkena3 : STRING; + port_clkena4 : STRING; + port_clkena5 : STRING; + port_extclk0 : STRING; + port_extclk1 : STRING; + port_extclk2 : STRING; + port_extclk3 : STRING; + self_reset_on_loss_lock : STRING; + width_clock : NATURAL + ); + PORT ( + areset : IN STD_LOGIC ; + clk : OUT STD_LOGIC_VECTOR (4 DOWNTO 0); + inclk : IN STD_LOGIC_VECTOR (1 DOWNTO 0); + locked : OUT STD_LOGIC + ); + END COMPONENT; + +BEGIN + sub_wire7_bv(0 DOWNTO 0) <= "0"; + sub_wire7 <= To_stdlogicvector(sub_wire7_bv); + sub_wire4 <= sub_wire0(2); + sub_wire3 <= sub_wire0(0); + sub_wire1 <= sub_wire0(1); + c1 <= sub_wire1; + locked <= sub_wire2; + c0 <= sub_wire3; + c2 <= sub_wire4; + sub_wire5 <= inclk0; + sub_wire6 <= sub_wire7(0 DOWNTO 0) & sub_wire5; + + altpll_component : altpll + GENERIC MAP ( + bandwidth_type => "AUTO", + clk0_divide_by => 1, + clk0_duty_cycle => 50, + clk0_multiply_by => 1, + clk0_phase_shift => "-3000", + clk1_divide_by => 1, + clk1_duty_cycle => 50, + clk1_multiply_by => 1, + clk1_phase_shift => "0", + clk2_divide_by => 1, + clk2_duty_cycle => 50, + clk2_multiply_by => 2, + clk2_phase_shift => "0", + compensate_clock => "CLK1", + inclk0_input_frequency => 20000, + intended_device_family => "Cyclone IV E", + lpm_hint => "CBX_MODULE_PREFIX=pll", + lpm_type => "altpll", + operation_mode => "NORMAL", + pll_type => "AUTO", + port_activeclock => "PORT_UNUSED", + port_areset => "PORT_USED", + port_clkbad0 => "PORT_UNUSED", + port_clkbad1 => "PORT_UNUSED", + port_clkloss => "PORT_UNUSED", + port_clkswitch => "PORT_UNUSED", + port_configupdate => "PORT_UNUSED", + port_fbin => "PORT_UNUSED", + port_inclk0 => "PORT_USED", + port_inclk1 => "PORT_UNUSED", + port_locked => "PORT_USED", + port_pfdena => "PORT_UNUSED", + port_phasecounterselect => "PORT_UNUSED", + port_phasedone => "PORT_UNUSED", + port_phasestep => "PORT_UNUSED", + port_phaseupdown => "PORT_UNUSED", + port_pllena => "PORT_UNUSED", + port_scanaclr => "PORT_UNUSED", + port_scanclk => "PORT_UNUSED", + port_scanclkena => "PORT_UNUSED", + port_scandata => "PORT_UNUSED", + port_scandataout => "PORT_UNUSED", + port_scandone => "PORT_UNUSED", + port_scanread => "PORT_UNUSED", + port_scanwrite => "PORT_UNUSED", + port_clk0 => "PORT_USED", + port_clk1 => "PORT_USED", + port_clk2 => "PORT_USED", + port_clk3 => "PORT_UNUSED", + port_clk4 => "PORT_UNUSED", + port_clk5 => "PORT_UNUSED", + port_clkena0 => "PORT_UNUSED", + port_clkena1 => "PORT_UNUSED", + port_clkena2 => "PORT_UNUSED", + port_clkena3 => "PORT_UNUSED", + port_clkena4 => "PORT_UNUSED", + port_clkena5 => "PORT_UNUSED", + port_extclk0 => "PORT_UNUSED", + port_extclk1 => "PORT_UNUSED", + port_extclk2 => "PORT_UNUSED", + port_extclk3 => "PORT_UNUSED", + self_reset_on_loss_lock => "OFF", + width_clock => 5 + ) + PORT MAP ( + areset => areset, + inclk => sub_wire6, + clk => sub_wire0, + locked => sub_wire2 + ); + + + +END SYN; + +-- ============================================================ +-- CNX file retrieval info +-- ============================================================ +-- Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0" +-- Retrieval info: PRIVATE: BANDWIDTH STRING "1.000" +-- Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1" +-- Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz" +-- Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low" +-- Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1" +-- Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0" +-- Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0" +-- Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0" +-- Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0" +-- Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0" +-- Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0" +-- Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0" +-- Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c1" +-- Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0" +-- Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "Any" +-- Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "1" +-- Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "1" +-- Retrieval info: PRIVATE: DIV_FACTOR2 NUMERIC "1" +-- Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000" +-- Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000" +-- Retrieval info: PRIVATE: DUTY_CYCLE2 STRING "50.00000000" +-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "100.000000" +-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "100.000000" +-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE2 STRING "100.000000" +-- Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0" +-- Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0" +-- Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1" +-- Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0" +-- Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0" +-- Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575" +-- Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1" +-- Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "50.000" +-- Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz" +-- Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000" +-- Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1" +-- Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1" +-- Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz" +-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E" +-- Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1" +-- Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1" +-- Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1" +-- Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available" +-- Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0" +-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg" +-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "deg" +-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT2 STRING "ps" +-- Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any" +-- Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0" +-- Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0" +-- Retrieval info: PRIVATE: MIRROR_CLK2 STRING "0" +-- Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "2" +-- Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "2" +-- Retrieval info: PRIVATE: MULT_FACTOR2 NUMERIC "2" +-- Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1" +-- Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "90.00000000" +-- Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "100.00000000" +-- Retrieval info: PRIVATE: OUTPUT_FREQ2 STRING "100.00000000" +-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0" +-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "0" +-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE2 STRING "0" +-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz" +-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz" +-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT2 STRING "MHz" +-- Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1" +-- Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0" +-- Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "-54.00000000" +-- Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000" +-- Retrieval info: PRIVATE: PHASE_SHIFT2 STRING "0.00000000" +-- Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0" +-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg" +-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg" +-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT2 STRING "ps" +-- Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0" +-- Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "1" +-- Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1" +-- Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0" +-- Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0" +-- Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0" +-- Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0" +-- Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0" +-- Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0" +-- Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0" +-- Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll.mif" +-- Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0" +-- Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1" +-- Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0" +-- Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0" +-- Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0" +-- Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000" +-- Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz" +-- Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500" +-- Retrieval info: PRIVATE: SPREAD_USE STRING "0" +-- Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0" +-- Retrieval info: PRIVATE: STICKY_CLK0 STRING "1" +-- Retrieval info: PRIVATE: STICKY_CLK1 STRING "1" +-- Retrieval info: PRIVATE: STICKY_CLK2 STRING "1" +-- Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1" +-- Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1" +-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +-- Retrieval info: PRIVATE: USE_CLK0 STRING "1" +-- Retrieval info: PRIVATE: USE_CLK1 STRING "1" +-- Retrieval info: PRIVATE: USE_CLK2 STRING "1" +-- Retrieval info: PRIVATE: USE_CLKENA0 STRING "0" +-- Retrieval info: PRIVATE: USE_CLKENA1 STRING "0" +-- Retrieval info: PRIVATE: USE_CLKENA2 STRING "0" +-- Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0" +-- Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0" +-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +-- Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "AUTO" +-- Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "1" +-- Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" +-- Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "2" +-- Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "-1500" +-- Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "1" +-- Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50" +-- Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "2" +-- Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0" +-- Retrieval info: CONSTANT: CLK2_DIVIDE_BY NUMERIC "1" +-- Retrieval info: CONSTANT: CLK2_DUTY_CYCLE NUMERIC "50" +-- Retrieval info: CONSTANT: CLK2_MULTIPLY_BY NUMERIC "2" +-- Retrieval info: CONSTANT: CLK2_PHASE_SHIFT STRING "0" +-- Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK1" +-- Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "20000" +-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone IV E" +-- Retrieval info: CONSTANT: LPM_TYPE STRING "altpll" +-- Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL" +-- Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO" +-- Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_USED" +-- Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED" +-- Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED" +-- Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED" +-- Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_USED" +-- Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_USED" +-- Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED" +-- Retrieval info: CONSTANT: SELF_RESET_ON_LOSS_LOCK STRING "OFF" +-- Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5" +-- Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]" +-- Retrieval info: USED_PORT: @inclk 0 0 2 0 INPUT_CLK_EXT VCC "@inclk[1..0]" +-- Retrieval info: USED_PORT: areset 0 0 0 0 INPUT GND "areset" +-- Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0" +-- Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1" +-- Retrieval info: USED_PORT: c2 0 0 0 0 OUTPUT_CLK_EXT VCC "c2" +-- Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0" +-- Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked" +-- Retrieval info: CONNECT: @areset 0 0 0 0 areset 0 0 0 0 +-- Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0 +-- Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0 +-- Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0 +-- Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1 +-- Retrieval info: CONNECT: c2 0 0 0 0 @clk 0 0 1 2 +-- Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0 +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll.vhd TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll.ppf TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll.inc FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll.cmp TRUE +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll.bsf FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL pll_inst.vhd FALSE +-- Retrieval info: LIB_FILE: altera_mf +-- Retrieval info: CBX_MODULE_PREFIX: ON \ No newline at end of file diff --git a/vhdl/board/de0_nano/top_level_de0_nano.vhd b/vhdl/board/de0_nano/top_level_de0_nano.vhd new file mode 100644 index 0000000..beeb818 --- /dev/null +++ b/vhdl/board/de0_nano/top_level_de0_nano.vhd @@ -0,0 +1,465 @@ +--+-----------------------------------+-------------------------------------+-- +--| ___ ___ | (c) 2013-2014 William R Sowerbutts |-- +--| ___ ___ ___ ___( _ ) / _ \ | will@sowerbutts.com |-- +--| / __|/ _ \ / __|_ / _ \| | | | | |-- +--| \__ \ (_) | (__ / / (_) | |_| | | A Z80 FPGA computer, just for fun |-- +--| |___/\___/ \___/___\___/ \___/ | |-- +--| | http://sowerbutts.com/ |-- +--+-----------------------------------+-------------------------------------+-- +--| Top level module: connects modules to each other and the outside world |-- +--+-------------------------------------------------------------------------+-- +-- +-- See README.txt for more details +-- + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.NUMERIC_STD.ALL; + +entity top_level is + Port ( sysclk_32m : in std_logic; + sys_clk_pad_i : in std_logic; + rst_n_pad_i : in std_logic; + leds : out std_logic_vector(4 downto 0); + reset_button : in std_logic; + console_select : in std_logic; + + -- UART0 (to FTDI USB chip, no flow control) + serial_rx : in std_logic; + serial_tx : out std_logic; + + -- UART0 (to MAX3232 level shifter chip, hardware flow control) + uart1_rx : in std_logic; + uart1_cts : in std_logic; + uart1_tx : out std_logic; + uart1_rts : out std_logic; + + -- SPI flash chip + flash_spi_cs : out std_logic; + flash_spi_clk : out std_logic; + flash_spi_mosi : out std_logic; + flash_spi_miso : in std_logic; + + -- SD card socket + sdcard_spi_cs : out std_logic; + sdcard_spi_clk : out std_logic; + sdcard_spi_mosi : out std_logic; + sdcard_spi_miso : in std_logic; + + -- SDRAM chip + SDRAM_CLK : out std_logic; + SDRAM_CKE : out std_logic; + SDRAM_CS : out std_logic; + SDRAM_nRAS : out std_logic; + SDRAM_nCAS : out std_logic; + SDRAM_nWE : out std_logic; + SDRAM_DQM : out std_logic_vector( 1 downto 0); + SDRAM_ADDR : out std_logic_vector (12 downto 0); + SDRAM_BA : out std_logic_vector( 1 downto 0); + SDRAM_DQ : inout std_logic_vector (15 downto 0) + ); +end top_level; + +architecture Behavioral of top_level is + constant clk_freq_mhz : natural := 50; -- this is the frequency which the PLL outputs, in MHz. + + -- SDRAM configuration + constant sdram_address_width : natural := 24; + constant sdram_column_bits : natural := 9; + constant cycles_per_refresh : natural := (64000*clk_freq_mhz)/8192-1; + + -- For simulation, we don't need a long init stage. but for real DRAM we need approx 101us. + -- The constant below has a different value when interpreted by the synthesis and simulator + -- tools in order to achieve the desired timing in each. + constant sdram_startup_cycles: natural := 101 * clk_freq_mhz + -- pragma translate_off + - 10000 -- reduce the value the simulator uses + -- pragma translate_on + ; + + -- signals for clocking + signal clk_feedback : std_logic; -- PLL clock feedback + signal clk_unbuffered : std_logic; -- unbuffered system clock + signal clk : std_logic; -- buffered system clock (all logic should be clocked by this) + + -- console latch + signal console_select_clk1 : std_logic; + signal console_select_sync : std_logic; + signal swap_uart01 : std_logic := '0'; + + -- system reset signals + signal power_on_reset : std_logic_vector(1 downto 0) := (others => '1'); + signal system_reset : std_logic; + signal reset_button_clk1 : std_logic; + signal reset_button_sync : std_logic; -- reset button signal, synchronised to our clock + signal reset_request_uart : std_logic; -- reset request signal from FTDI UART (when you send "!~!~!~" to the UART, this line is asserted) + + -- CPU control + signal coldboot : std_logic; + signal cpu_clk_enable : std_logic; + signal cpu_m1_cycle : std_logic; + signal cpu_req_mem : std_logic; + signal cpu_req_io : std_logic; + signal req_mem : std_logic; + signal req_io : std_logic; + signal req_read : std_logic; + signal req_write : std_logic; + signal virtual_address : std_logic_vector(15 downto 0); + signal physical_address : std_logic_vector(25 downto 0); + signal mem_wait : std_logic; + signal cpu_wait : std_logic; + signal dram_wait : std_logic; + signal mmu_wait : std_logic; + signal spimaster0_wait : std_logic; + signal spimaster1_wait : std_logic; + + -- chip selects + signal mmu_cs : std_logic; + signal rom_cs : std_logic; + signal sram_cs : std_logic; + signal dram_cs : std_logic; + signal uartA_cs : std_logic; + signal uartB_cs : std_logic; + signal uart0_cs : std_logic; + signal uart1_cs : std_logic; + signal timer_cs : std_logic; + signal spimaster0_cs : std_logic; + signal spimaster1_cs : std_logic; + signal clkscale_cs : std_logic; + signal gpio_cs : std_logic; + + -- data bus + signal cpu_data_in : std_logic_vector(7 downto 0); + signal cpu_data_out : std_logic_vector(7 downto 0); + signal rom_data_out : std_logic_vector(7 downto 0); + signal sram_data_out : std_logic_vector(7 downto 0); + signal dram_data_out : std_logic_vector(7 downto 0); + signal uart0_data_out : std_logic_vector(7 downto 0); + signal uart1_data_out : std_logic_vector(7 downto 0); + signal timer_data_out : std_logic_vector(7 downto 0); + signal spimaster0_data_out : std_logic_vector(7 downto 0); + signal spimaster1_data_out : std_logic_vector(7 downto 0); + signal mmu_data_out : std_logic_vector(7 downto 0); + signal clkscale_out : std_logic_vector(7 downto 0); + signal gpio_data_out : std_logic_vector(7 downto 0); + + -- GPIO + signal gpio_input : std_logic_vector(7 downto 0); + signal gpio_output : std_logic_vector(7 downto 0); + + -- Interrupts + signal cpu_interrupt_in : std_logic; + signal timer_interrupt : std_logic; + signal uart0_interrupt : std_logic; + signal uart1_interrupt : std_logic; + +begin + -- Hold CPU reset high for 8 clock cycles on startup, + -- and when the user presses their reset button. + process(clk) + begin + if rising_edge(clk) then + -- Xilinx advises using two flip-flops are used to bring external + -- signals which feed control logic into our clock domain. + reset_button_clk1 <= reset_button; + reset_button_sync <= reset_button_clk1; + console_select_clk1 <= console_select; + console_select_sync <= console_select_clk1; + + -- reset the system when requested + if (power_on_reset(0) = '1') then + system_reset <= '1'; + else + system_reset <= '0'; + end if; + + -- shift 0s into the power_on_reset shift register from the MSB + power_on_reset <= '0' & power_on_reset(power_on_reset'length-1 downto 1); + + -- During reset, latch the console select jumper. This is used to + -- optionally swap over the UART roles and move the system console to + -- the second serial port on the IO board. + if system_reset = '1' then + swap_uart01 <= console_select_sync; + else + swap_uart01 <= swap_uart01; + end if; + end if; + end process; + + -- GPIO input signal routing + gpio_input <= coldboot & swap_uart01 & "000000"; + + -- GPIO output signal routing + leds(0) <= gpio_output(0); + leds(1) <= gpio_output(1); + leds(2) <= gpio_output(2); + leds(3) <= gpio_output(3); + + -- User LED (LED1) on Papilio Pro indicates when the CPU is being asked to wait (eg by the SDRAM cache) + leds(4) <= cpu_wait; + + -- Interrupt signal for the CPU + cpu_interrupt_in <= (timer_interrupt or uart0_interrupt or uart1_interrupt); + + -- Z80 CPU core + cpu: entity work.Z80cpu + port map ( + reset => system_reset, + clk => clk, + clk_enable => cpu_clk_enable, + m1_cycle => cpu_m1_cycle, + interrupt => cpu_interrupt_in, + nmi => '0', + req_mem => cpu_req_mem, + req_io => cpu_req_io, + req_read => req_read, + req_write => req_write, + mem_wait => cpu_wait, + address => virtual_address, + data_in => cpu_data_in, + data_out => cpu_data_out + ); + + -- Memory management unit + mmu: entity work.MMU + port map ( + reset => system_reset, + clk => clk, + address_in => virtual_address, + address_out => physical_address, + cpu_data_in => cpu_data_out, + cpu_data_out => mmu_data_out, + req_mem_in => cpu_req_mem, + req_io_in => cpu_req_io, + req_mem_out => req_mem, + req_io_out => req_io, + req_read => req_read, + req_write => req_write, + io_cs => mmu_cs, + cpu_wait => mmu_wait, + access_violated => open -- for now!! + ); + + -- This process determines which IO or memory device the CPU is addressing + -- and asserts the appropriate chip select signals. + cs_process: process(req_mem, req_io, physical_address, virtual_address, uartA_cs, uartB_cs, swap_uart01) + begin + -- memory chip selects: default to unselected + rom_cs <= '0'; + sram_cs <= '0'; + dram_cs <= '0'; + + -- io chip selects: default to unselected + uartA_cs <= '0'; + uartB_cs <= '0'; + mmu_cs <= '0'; + timer_cs <= '0'; + spimaster0_cs <= '0'; + spimaster1_cs <= '0'; + clkscale_cs <= '0'; + gpio_cs <= '0'; + + -- memory address decoding + -- address space is organised as: + -- 0x0 000 000 - 0x0 FFF FFF 16MB DRAM (cached) (mapped to 8MB DRAM twice) + -- 0x1 000 000 - 0x1 FFF FFF 16MB DRAM (uncached) (mapped to 8MB DRAM twice) + -- 0x2 000 000 - 0x2 000 FFF 4KB monitor ROM (FPGA block RAM) + -- 0x2 001 000 - 0x2 001 FFF 4KB SRAM (FPGA block RAM) + -- 0x2 002 000 - 0x3 FFF FFF unused space for future expansion + if physical_address(25) = '0' then + -- bottom 32MB: DRAM handles this + dram_cs <= req_mem; + else + -- top 32MB: other memory devices + case physical_address(24 downto 12) is + when "0000000000000" => rom_cs <= req_mem; + when "0000000000001" => sram_cs <= req_mem; + when others => -- undecoded memory space + end case; + end if; + + -- IO address decoding + case virtual_address(7 downto 3) is + when "00000" => uartA_cs <= req_io; -- 00 ... 07 + when "00010" => timer_cs <= req_io; -- 10 ... 17 + when "00011" => spimaster0_cs <= req_io; -- 18 ... 1F + when "00100" => gpio_cs <= req_io; -- 20 ... 27 + when "00101" => uartB_cs <= req_io; -- 28 ... 2F + when "00110" => spimaster1_cs <= req_io; -- 30 ... 37 + -- unused ports + when "11110" => clkscale_cs <= req_io; -- F0 ... F7 + when "11111" => mmu_cs <= req_io; -- F8 ... FF + when others => + end case; + + -- send the UART chip select to the appropriate UART depending + -- on whether they have been swapped over or not. + if swap_uart01 = '0' then + uart0_cs <= uartB_cs; + uart1_cs <= uartA_cs; + else + uart0_cs <= uartA_cs; + uart1_cs <= uartB_cs; + end if; + end process; + + -- the selected memory device can request the CPU to wait + mem_wait <= + dram_wait when dram_cs='1' else + spimaster0_wait when spimaster0_cs='1' else + spimaster1_wait when spimaster1_cs='1' else + '0'; + + -- the MMU can, at any time, request the CPU wait (this is used when + -- translating IO to memory requests, to implement a wait state for + -- the "17th page") + cpu_wait <= (mem_wait or mmu_wait); + + -- input mux for CPU data bus + cpu_data_in <= + rom_data_out when rom_cs='1' else + dram_data_out when dram_cs='1' else + sram_data_out when sram_cs='1' else + uart0_data_out when uart0_cs='1' else + uart1_data_out when uart1_cs='1' else + timer_data_out when timer_cs='1' else + mmu_data_out when mmu_cs='1' else + spimaster0_data_out when spimaster0_cs='1' else + spimaster1_data_out when spimaster1_cs='1' else + clkscale_out when clkscale_cs='1' else + gpio_data_out when gpio_cs='1' else + rom_data_out; -- default case + + dram: entity work.DRAM + generic map( + sdram_address_width => sdram_address_width, + sdram_column_bits => sdram_column_bits, + sdram_startup_cycles=> sdram_startup_cycles, + cycles_per_refresh => cycles_per_refresh + ) + port map( + clk => clk, + reset => '0', -- important to note that we DO NOT reset the SDRAM controller on reset (it would stop refreshing, which would be bad) + + -- interface to synthetic CPU + cs => dram_cs, + req_read => req_read, + req_write => req_write, + mem_address => physical_address(24 downto 0), + mem_wait => dram_wait, + data_in => cpu_data_out, + data_out => dram_data_out, + coldboot => coldboot, + + -- interface to hardware SDRAM chip + SDRAM_CLK => open, + SDRAM_CKE => SDRAM_CKE, + SDRAM_CS => SDRAM_CS, + SDRAM_nRAS => SDRAM_nRAS, + SDRAM_nCAS => SDRAM_nCAS, + SDRAM_nWE => SDRAM_nWE, + SDRAM_DQM => SDRAM_DQM, + SDRAM_BA => SDRAM_BA, + SDRAM_ADDR => SDRAM_ADDR, + SDRAM_DQ => SDRAM_DQ + ); + + -- 4KB system ROM implemented in block RAM + rom: entity work.MonZ80 + port map( + clk => clk, + A => physical_address(11 downto 0), + D => rom_data_out + ); + + -- 4KB SRAM memory implemented in block RAM + sram: entity work.SSRAM + generic map( + AddrWidth => 12 + ) + port map( + clk => clk, + ce => sram_cs, + we => req_write, + A => physical_address(11 downto 0), + DIn => cpu_data_out, + DOut => sram_data_out + ); + + -- UART connected to FTDI USB UART + uart0: entity work.uart_interface + generic map ( watch_for_reset => 1, clk_frequency => (clk_freq_mhz * 1000000) ) + port map( + clk => clk, + reset => system_reset, + reset_out => reset_request_uart, -- result of watching for reset sequence on the input + serial_in => serial_rx, + serial_out => serial_tx, + serial_rts => open, + serial_cts => '0', + cpu_address => virtual_address(2 downto 0), + cpu_data_in => cpu_data_out, + cpu_data_out => uart0_data_out, + enable => uart0_cs, + interrupt => uart0_interrupt, + req_read => req_read, + req_write => req_write + ); + + -- Timer device (internally scales the clock to 1MHz) + timer: entity work.timer + generic map ( clk_frequency => (clk_freq_mhz * 1000000) ) + port map( + clk => clk, + reset => system_reset, + cpu_address => virtual_address(2 downto 0), + data_in => cpu_data_out, + data_out => timer_data_out, + enable => timer_cs, + req_read => req_read, + req_write => req_write, + interrupt => timer_interrupt + ); + + -- GPIO to FPGA pins and/or internal signals + gpio: entity work.gpio + port map( + clk => clk, + reset => system_reset, + cpu_address => virtual_address(2 downto 0), + data_in => cpu_data_out, + data_out => gpio_data_out, + enable => gpio_cs, + read_notwrite => req_read, + input_pins => gpio_input, + output_pins => gpio_output + ); + + -- An attempt to allow the CPU clock to be scaled back to run + -- at slower speeds without affecting the clock signal sent to + -- IO devices. Basically this was an attempt to make CP/M games + -- playable :) Very limited success. Might be simpler to remove + -- this entirely. + clkscale: entity work.clkscale + port map ( + clk => clk, + reset => system_reset, + cpu_address => virtual_address(2 downto 0), + data_in => cpu_data_out, + data_out => clkscale_out, + enable => clkscale_cs, + read_notwrite => req_read, + clk_enable => cpu_clk_enable + ); + + pll: entity work.pll + port map ( + areset => open, + inclk0 => sys_clk_pad_i, + c0 => sdram_clk, -- 100 Mhz - 180 deg + c1 => clk, -- 100 Mhz + locked => open + ); + +end Behavioral; diff --git a/vhdl/board/de2/top_level_de2.vhd b/vhdl/board/de2/top_level_de2.vhd new file mode 100644 index 0000000..ab9b756 --- /dev/null +++ b/vhdl/board/de2/top_level_de2.vhd @@ -0,0 +1,466 @@ +--+-----------------------------------+-------------------------------------+-- +--| ___ ___ | (c) 2013-2014 William R Sowerbutts |-- +--| ___ ___ ___ ___( _ ) / _ \ | will@sowerbutts.com |-- +--| / __|/ _ \ / __|_ / _ \| | | | | |-- +--| \__ \ (_) | (__ / / (_) | |_| | | A Z80 FPGA computer, just for fun |-- +--| |___/\___/ \___/___\___/ \___/ | |-- +--| | http://sowerbutts.com/ |-- +--+-----------------------------------+-------------------------------------+-- +--| Top level module: connects modules to each other and the outside world |-- +--+-------------------------------------------------------------------------+-- +-- +-- See README.txt for more details +-- + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.NUMERIC_STD.ALL; +use work.T80_Pack.ALL; + +entity top_level is + Port ( sysclk_32m : in std_logic; + sys_clk_pad_i : in std_logic; + rst_n_pad_i : in std_logic; + leds : out std_logic_vector(4 downto 0); + reset_button : in std_logic; + console_select : in std_logic; + + -- UART0 (to FTDI USB chip, no flow control) + serial_rx : in std_logic; + serial_tx : out std_logic; + + -- UART0 (to MAX3232 level shifter chip, hardware flow control) + uart1_rx : in std_logic; + uart1_cts : in std_logic; + uart1_tx : out std_logic; + uart1_rts : out std_logic; + + -- SPI flash chip + flash_spi_cs : out std_logic; + flash_spi_clk : out std_logic; + flash_spi_mosi : out std_logic; + flash_spi_miso : in std_logic; + + -- SD card socket + sdcard_spi_cs : out std_logic; + sdcard_spi_clk : out std_logic; + sdcard_spi_mosi : out std_logic; + sdcard_spi_miso : in std_logic; + + -- SDRAM chip + SDRAM_CLK : out std_logic; + SDRAM_CKE : out std_logic; + SDRAM_CS : out std_logic; + SDRAM_nRAS : out std_logic; + SDRAM_nCAS : out std_logic; + SDRAM_nWE : out std_logic; + SDRAM_DQM : out std_logic_vector( 1 downto 0); + SDRAM_ADDR : out std_logic_vector (12 downto 0); + SDRAM_BA : out std_logic_vector( 1 downto 0); + SDRAM_DQ : inout std_logic_vector (15 downto 0) + ); +end top_level; + +architecture Behavioral of top_level is + constant clk_freq_mhz : natural := 50; -- this is the frequency which the PLL outputs, in MHz. + + -- SDRAM configuration + constant sdram_address_width : natural := 24; + constant sdram_column_bits : natural := 9; + constant cycles_per_refresh : natural := (64000*clk_freq_mhz)/8192-1; + + -- For simulation, we don't need a long init stage. but for real DRAM we need approx 101us. + -- The constant below has a different value when interpreted by the synthesis and simulator + -- tools in order to achieve the desired timing in each. + constant sdram_startup_cycles: natural := 101 * clk_freq_mhz + -- pragma translate_off + - 10000 -- reduce the value the simulator uses + -- pragma translate_on + ; + + -- signals for clocking + signal clk_feedback : std_logic; -- PLL clock feedback + signal clk_unbuffered : std_logic; -- unbuffered system clock + signal clk : std_logic; -- buffered system clock (all logic should be clocked by this) + + -- console latch + signal console_select_clk1 : std_logic; + signal console_select_sync : std_logic; + signal swap_uart01 : std_logic := '0'; + + -- system reset signals + signal power_on_reset : std_logic_vector(1 downto 0) := (others => '1'); + signal system_reset : std_logic; + signal reset_button_clk1 : std_logic; + signal reset_button_sync : std_logic; -- reset button signal, synchronised to our clock + signal reset_request_uart : std_logic; -- reset request signal from FTDI UART (when you send "!~!~!~" to the UART, this line is asserted) + + -- CPU control + signal coldboot : std_logic; + signal cpu_clk_enable : std_logic; + signal cpu_m1_cycle : std_logic; + signal cpu_req_mem : std_logic; + signal cpu_req_io : std_logic; + signal req_mem : std_logic; + signal req_io : std_logic; + signal req_read : std_logic; + signal req_write : std_logic; + signal virtual_address : std_logic_vector(15 downto 0); + signal physical_address : std_logic_vector(25 downto 0); + signal mem_wait : std_logic; + signal cpu_wait : std_logic; + signal dram_wait : std_logic; + signal mmu_wait : std_logic; + signal spimaster0_wait : std_logic; + signal spimaster1_wait : std_logic; + + -- chip selects + signal mmu_cs : std_logic; + signal rom_cs : std_logic; + signal sram_cs : std_logic; + signal dram_cs : std_logic; + signal uartA_cs : std_logic; + signal uartB_cs : std_logic; + signal uart0_cs : std_logic; + signal uart1_cs : std_logic; + signal timer_cs : std_logic; + signal spimaster0_cs : std_logic; + signal spimaster1_cs : std_logic; + signal clkscale_cs : std_logic; + signal gpio_cs : std_logic; + + -- data bus + signal cpu_data_in : std_logic_vector(7 downto 0); + signal cpu_data_out : std_logic_vector(7 downto 0); + signal rom_data_out : std_logic_vector(7 downto 0); + signal sram_data_out : std_logic_vector(7 downto 0); + signal dram_data_out : std_logic_vector(7 downto 0); + signal uart0_data_out : std_logic_vector(7 downto 0); + signal uart1_data_out : std_logic_vector(7 downto 0); + signal timer_data_out : std_logic_vector(7 downto 0); + signal spimaster0_data_out : std_logic_vector(7 downto 0); + signal spimaster1_data_out : std_logic_vector(7 downto 0); + signal mmu_data_out : std_logic_vector(7 downto 0); + signal clkscale_out : std_logic_vector(7 downto 0); + signal gpio_data_out : std_logic_vector(7 downto 0); + + -- GPIO + signal gpio_input : std_logic_vector(7 downto 0); + signal gpio_output : std_logic_vector(7 downto 0); + + -- Interrupts + signal cpu_interrupt_in : std_logic; + signal timer_interrupt : std_logic; + signal uart0_interrupt : std_logic; + signal uart1_interrupt : std_logic; + +begin + -- Hold CPU reset high for 8 clock cycles on startup, + -- and when the user presses their reset button. + process(clk) + begin + if rising_edge(clk) then + -- Xilinx advises using two flip-flops are used to bring external + -- signals which feed control logic into our clock domain. + reset_button_clk1 <= reset_button; + reset_button_sync <= reset_button_clk1; + console_select_clk1 <= console_select; + console_select_sync <= console_select_clk1; + + -- reset the system when requested + if (power_on_reset(0) = '1') then + system_reset <= '1'; + else + system_reset <= '0'; + end if; + + -- shift 0s into the power_on_reset shift register from the MSB + power_on_reset <= '0' & power_on_reset(power_on_reset'length-1 downto 1); + + -- During reset, latch the console select jumper. This is used to + -- optionally swap over the UART roles and move the system console to + -- the second serial port on the IO board. + if system_reset = '1' then + swap_uart01 <= console_select_sync; + else + swap_uart01 <= swap_uart01; + end if; + end if; + end process; + + -- GPIO input signal routing + gpio_input <= coldboot & swap_uart01 & "000000"; + + -- GPIO output signal routing + leds(0) <= gpio_output(0); + leds(1) <= gpio_output(1); + leds(2) <= gpio_output(2); + leds(3) <= gpio_output(3); + + -- User LED (LED1) on Papilio Pro indicates when the CPU is being asked to wait (eg by the SDRAM cache) + leds(4) <= cpu_wait; + + -- Interrupt signal for the CPU + cpu_interrupt_in <= (timer_interrupt or uart0_interrupt or uart1_interrupt); + + -- Z80 CPU core + cpu: entity work.Z80cpu + port map ( + reset => system_reset, + clk => clk, + clk_enable => cpu_clk_enable, + m1_cycle => cpu_m1_cycle, + interrupt => cpu_interrupt_in, + nmi => '0', + req_mem => cpu_req_mem, + req_io => cpu_req_io, + req_read => req_read, + req_write => req_write, + mem_wait => cpu_wait, + address => virtual_address, + data_in => cpu_data_in, + data_out => cpu_data_out + ); + + -- Memory management unit + mmu: entity work.MMU + port map ( + reset => system_reset, + clk => clk, + address_in => virtual_address, + address_out => physical_address, + cpu_data_in => cpu_data_out, + cpu_data_out => mmu_data_out, + req_mem_in => cpu_req_mem, + req_io_in => cpu_req_io, + req_mem_out => req_mem, + req_io_out => req_io, + req_read => req_read, + req_write => req_write, + io_cs => mmu_cs, + cpu_wait => mmu_wait, + access_violated => open -- for now!! + ); + + -- This process determines which IO or memory device the CPU is addressing + -- and asserts the appropriate chip select signals. + cs_process: process(req_mem, req_io, physical_address, virtual_address, uartA_cs, uartB_cs, swap_uart01) + begin + -- memory chip selects: default to unselected + rom_cs <= '0'; + sram_cs <= '0'; + dram_cs <= '0'; + + -- io chip selects: default to unselected + uartA_cs <= '0'; + uartB_cs <= '0'; + mmu_cs <= '0'; + timer_cs <= '0'; + spimaster0_cs <= '0'; + spimaster1_cs <= '0'; + clkscale_cs <= '0'; + gpio_cs <= '0'; + + -- memory address decoding + -- address space is organised as: + -- 0x0 000 000 - 0x0 FFF FFF 16MB DRAM (cached) (mapped to 8MB DRAM twice) + -- 0x1 000 000 - 0x1 FFF FFF 16MB DRAM (uncached) (mapped to 8MB DRAM twice) + -- 0x2 000 000 - 0x2 000 FFF 4KB monitor ROM (FPGA block RAM) + -- 0x2 001 000 - 0x2 001 FFF 4KB SRAM (FPGA block RAM) + -- 0x2 002 000 - 0x3 FFF FFF unused space for future expansion + if physical_address(25) = '0' then + -- bottom 32MB: DRAM handles this + dram_cs <= req_mem; + else + -- top 32MB: other memory devices + case physical_address(24 downto 12) is + when "0000000000000" => rom_cs <= req_mem; + when "0000000000001" => sram_cs <= req_mem; + when others => -- undecoded memory space + end case; + end if; + + -- IO address decoding + case virtual_address(7 downto 3) is + when "00000" => uartA_cs <= req_io; -- 00 ... 07 + when "00010" => timer_cs <= req_io; -- 10 ... 17 + when "00011" => spimaster0_cs <= req_io; -- 18 ... 1F + when "00100" => gpio_cs <= req_io; -- 20 ... 27 + when "00101" => uartB_cs <= req_io; -- 28 ... 2F + when "00110" => spimaster1_cs <= req_io; -- 30 ... 37 + -- unused ports + when "11110" => clkscale_cs <= req_io; -- F0 ... F7 + when "11111" => mmu_cs <= req_io; -- F8 ... FF + when others => + end case; + + -- send the UART chip select to the appropriate UART depending + -- on whether they have been swapped over or not. + if swap_uart01 = '0' then + uart0_cs <= uartB_cs; + uart1_cs <= uartA_cs; + else + uart0_cs <= uartA_cs; + uart1_cs <= uartB_cs; + end if; + end process; + + -- the selected memory device can request the CPU to wait + mem_wait <= + dram_wait when dram_cs='1' else + spimaster0_wait when spimaster0_cs='1' else + spimaster1_wait when spimaster1_cs='1' else + '0'; + + -- the MMU can, at any time, request the CPU wait (this is used when + -- translating IO to memory requests, to implement a wait state for + -- the "17th page") + cpu_wait <= (mem_wait or mmu_wait); + + -- input mux for CPU data bus + cpu_data_in <= + rom_data_out when rom_cs='1' else + dram_data_out when dram_cs='1' else + sram_data_out when sram_cs='1' else + uart0_data_out when uart0_cs='1' else + uart1_data_out when uart1_cs='1' else + timer_data_out when timer_cs='1' else + mmu_data_out when mmu_cs='1' else + spimaster0_data_out when spimaster0_cs='1' else + spimaster1_data_out when spimaster1_cs='1' else + clkscale_out when clkscale_cs='1' else + gpio_data_out when gpio_cs='1' else + rom_data_out; -- default case + + dram: entity work.DRAM + generic map( + sdram_address_width => sdram_address_width, + sdram_column_bits => sdram_column_bits, + sdram_startup_cycles=> sdram_startup_cycles, + cycles_per_refresh => cycles_per_refresh + ) + port map( + clk => clk, + reset => '0', -- important to note that we DO NOT reset the SDRAM controller on reset (it would stop refreshing, which would be bad) + + -- interface to synthetic CPU + cs => dram_cs, + req_read => req_read, + req_write => req_write, + mem_address => physical_address(24 downto 0), + mem_wait => dram_wait, + data_in => cpu_data_out, + data_out => dram_data_out, + coldboot => coldboot, + + -- interface to hardware SDRAM chip + SDRAM_CLK => open, + SDRAM_CKE => SDRAM_CKE, + SDRAM_CS => SDRAM_CS, + SDRAM_nRAS => SDRAM_nRAS, + SDRAM_nCAS => SDRAM_nCAS, + SDRAM_nWE => SDRAM_nWE, + SDRAM_DQM => SDRAM_DQM, + SDRAM_BA => SDRAM_BA, + SDRAM_ADDR => SDRAM_ADDR, + SDRAM_DQ => SDRAM_DQ + ); + + -- 4KB system ROM implemented in block RAM + rom: entity work.MonZ80 + port map( + clk => clk, + A => physical_address(11 downto 0), + D => rom_data_out + ); + + -- 4KB SRAM memory implemented in block RAM + sram: entity work.SSRAM + generic map( + AddrWidth => 12 + ) + port map( + clk => clk, + ce => sram_cs, + we => req_write, + A => physical_address(11 downto 0), + DIn => cpu_data_out, + DOut => sram_data_out + ); + + -- UART connected to FTDI USB UART + uart0: entity work.uart_interface + generic map ( watch_for_reset => 1, clk_frequency => (clk_freq_mhz * 1000000) ) + port map( + clk => clk, + reset => system_reset, + reset_out => reset_request_uart, -- result of watching for reset sequence on the input + serial_in => serial_rx, + serial_out => serial_tx, + serial_rts => open, + serial_cts => '0', + cpu_address => virtual_address(2 downto 0), + cpu_data_in => cpu_data_out, + cpu_data_out => uart0_data_out, + enable => uart0_cs, + interrupt => uart0_interrupt, + req_read => req_read, + req_write => req_write + ); + + -- Timer device (internally scales the clock to 1MHz) + timer: entity work.timer + generic map ( clk_frequency => (clk_freq_mhz * 1000000) ) + port map( + clk => clk, + reset => system_reset, + cpu_address => virtual_address(2 downto 0), + data_in => cpu_data_out, + data_out => timer_data_out, + enable => timer_cs, + req_read => req_read, + req_write => req_write, + interrupt => timer_interrupt + ); + + -- GPIO to FPGA pins and/or internal signals + gpio: entity work.gpio + port map( + clk => clk, + reset => system_reset, + cpu_address => virtual_address(2 downto 0), + data_in => cpu_data_out, + data_out => gpio_data_out, + enable => gpio_cs, + read_notwrite => req_read, + input_pins => gpio_input, + output_pins => gpio_output + ); + + -- An attempt to allow the CPU clock to be scaled back to run + -- at slower speeds without affecting the clock signal sent to + -- IO devices. Basically this was an attempt to make CP/M games + -- playable :) Very limited success. Might be simpler to remove + -- this entirely. + clkscale: entity work.clkscale + port map ( + clk => clk, + reset => system_reset, + cpu_address => virtual_address(2 downto 0), + data_in => cpu_data_out, + data_out => clkscale_out, + enable => clkscale_cs, + read_notwrite => req_read, + clk_enable => cpu_clk_enable + ); + + pll: entity work.pll + port map ( + areset => open, + inclk0 => sys_clk_pad_i, + c0 => sdram_clk, -- 100 Mhz - 180 deg + c1 => clk, -- 100 Mhz + locked => open + ); + +end Behavioral; From b29d3d070131fb5fe52ed0321fa0c85be3fd092d Mon Sep 17 00:00:00 2001 From: "Sergio L. Pascual" Date: Thu, 22 Jan 2015 01:06:56 +0100 Subject: [PATCH 3/4] Update README. --- README.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/README.md b/README.md index 1a44758..3a64f5e 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ socz80-de0_nano =============== -This is a port of Will Sowerbutts' socz80 retro microcomputer (http://sowerbutts.com/socz80) for the Tersasic DE0-nano board. +This is a port of Will Sowerbutts' socz80 retro microcomputer (http://sowerbutts.com/socz80) for Altera FPGA boards, currently supporting DE0-nano, DE2 and DE2-70 from Terasic. Building ======== @@ -13,9 +13,3 @@ Software This project only contains the VHDL files for building the core and its depencies. You can find some software for this microcomputer and instructions about what you can do with it inside the tarball of the original project (http://sowerbutts.com/socz80/socz80-2014-04-30.tar.gz). -TODO -==== - -* To be able to get this design to run on the DE0-nano without breaking the timing constrains in excess, I had to remove the block RAM based cache. Even without this component, the design barely accomodates to said contrains. A better solution would probably be implementing an arbiter for the SDRAM, allowing this one and its controller to run at 100 Mhz, while the rest of the components run at ~70 Mhz. - -* The original design was developed for a Papilo Pro board, which feautres a reasonable amount of non volatile memory onboard. The DE0-nano only provides a 2KB EEPROM, so I'm thinking about adding an SD card (using its SPI mode) to the design, for storing the ramdisks needed for running CP/M. From b1d79c12153827276e17bd9417a69570aeedcdd7 Mon Sep 17 00:00:00 2001 From: "Sergio L. Pascual" Date: Thu, 22 Jan 2015 01:07:56 +0100 Subject: [PATCH 4/4] Update README. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3a64f5e..ffa7832 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -socz80-de0_nano +socz80-altera =============== This is a port of Will Sowerbutts' socz80 retro microcomputer (http://sowerbutts.com/socz80) for Altera FPGA boards, currently supporting DE0-nano, DE2 and DE2-70 from Terasic.