Merge with upstream changes, espcially changes for seamless support of differents board.

This commit is contained in:
Godzil 2015-02-22 23:44:16 +00:00
commit 05f9db46ab
28 changed files with 5028 additions and 121 deletions

28
.gitignore vendored
View File

@ -1,6 +1,22 @@
*.bak
output_files/
db/
greybox_tmp/
incremental_db/
simulation/
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

View File

@ -1,7 +1,8 @@
socz80-de0
==========
socz80-altera
===============
This is a port of Will Sowerbutts' socz80 retro microcomputer (http://sowerbutts.com/socz80) for the Tersasic DE0 board based on the DE0 nano port from https://github.com/slp/socz80-de0_nano.
This is a port of Will Sowerbutts' socz80 retro microcomputer (http://sowerbutts.com/socz80) for Altera FPGA boards, currently supporting DE0, DE0-nano, DE2 and DE2-70 from Terasic.
Original version come from https://github.com/slp/socz80-altera
Building
========
@ -21,5 +22,5 @@ TODO
* Video Out and PS2 for a keyboard could be also a nice entry.
* Currently the 4 hex digit are used to show the CPU PC, but I will also create an IO device to show on them the value you want
* Also add all the SW switch and Button 1 and 2 to GPI and the LED to GPO minus the one used to display the CPU status. and Button 0 is used for Reset.
* The original design was developed for a Papilo Pro board, which feautres a reasonable amount of non volatile memory onboard. The DE0 have a flash device, it may be nice to allow to map it to memory. Not sure if allow write to it is a good idea.
* The original design was developed for a Papilo Pro board, which featres a reasonable amount of non volatile memory onboard. The DE0 have a flash device, it may be nice to allow to map it to memory. Not sure if allow write to it is a good idea.
* Also the two GPIO header could be added to the IO mapping.

View File

@ -20,8 +20,8 @@ sta: asm
quartus_sta $(QUARTUS_OPTIONS) $(DESIGN_NAME)
load: asm
quartus_pgm --mode=jtag -o p\;output_files/$(DESIGN_NAME).sof
quartus_pgm --mode=jtag -o p\;$(DESIGN_NAME).sof
loadonly:
quartus_sh $(QUARTUS_OPTIONS)
quartus_pgm --mode=jtag -o p\;output_files/$(DESIGN_NAME).sof
quartus_pgm --mode=jtag -o p\;$(DESIGN_NAME).sof

View File

@ -62,28 +62,31 @@ 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)"
# VHDL Files
set_global_assignment -name VHDL_FILE vhdl/DE0_SEG7.vhd
set_global_assignment -name VHDL_FILE vhdl/uart_interface.vhd
set_global_assignment -name VHDL_FILE vhdl/uart.vhd
set_global_assignment -name VHDL_FILE vhdl/top_level.vhd
set_global_assignment -name VHDL_FILE vhdl/timer.vhd
set_global_assignment -name VHDL_FILE vhdl/T80se.vhd
set_global_assignment -name VHDL_FILE vhdl/T80_Reg.vhd
set_global_assignment -name VHDL_FILE vhdl/T80_Pack.vhd
set_global_assignment -name VHDL_FILE vhdl/T80_MCode.vhd
set_global_assignment -name VHDL_FILE vhdl/T80_ALU.vhd
set_global_assignment -name VHDL_FILE vhdl/T80.vhd
set_global_assignment -name VHDL_FILE vhdl/SSRAM.vhd
set_global_assignment -name VHDL_FILE vhdl/SDRAM_Controller.vhd
set_global_assignment -name VHDL_FILE vhdl/pll.vhd
set_global_assignment -name VHDL_FILE vhdl/MonZ80.vhd
set_global_assignment -name VHDL_FILE vhdl/MMU.vhd
set_global_assignment -name VHDL_FILE vhdl/gpio.vhd
set_global_assignment -name VHDL_FILE vhdl/fifo.vhd
set_global_assignment -name VHDL_FILE vhdl/DRAM.vhd
set_global_assignment -name VHDL_FILE vhdl/spimaster.vhd
set_global_assignment -name VHDL_FILE vhdl/clkscale.vhd
set_global_assignment -name VHDL_FILE vhdl/Z80cpu.vhd
set_global_assignment -name VHDL_FILE ../../vhdl/board/de0/DE0_SEG7.vhd
set_global_assignment -name VHDL_FILE ../../vhdl/uart_interface.vhd
set_global_assignment -name VHDL_FILE ../../vhdl/uart.vhd
set_global_assignment -name VHDL_FILE ../../vhdl/board/de0/top_level_de0.vhd
set_global_assignment -name VHDL_FILE ../../vhdl/timer.vhd
set_global_assignment -name VHDL_FILE ../../vhdl/T80se.vhd
set_global_assignment -name VHDL_FILE ../../vhdl/T80_Reg.vhd
set_global_assignment -name VHDL_FILE ../../vhdl/T80_Pack.vhd
set_global_assignment -name VHDL_FILE ../../vhdl/T80_MCode.vhd
set_global_assignment -name VHDL_FILE ../../vhdl/T80_ALU.vhd
set_global_assignment -name VHDL_FILE ../../vhdl/T80.vhd
set_global_assignment -name VHDL_FILE ../../vhdl/SSRAM.vhd
set_global_assignment -name VHDL_FILE ../../vhdl/board/de0/SDRAM_Controller.vhd
set_global_assignment -name VHDL_FILE ../../vhdl/board/de0/pll_de0.vhd
set_global_assignment -name VHDL_FILE ../../vhdl/MonZ80.vhd
set_global_assignment -name VHDL_FILE ../../vhdl/MMU.vhd
set_global_assignment -name VHDL_FILE ../../vhdl/gpio.vhd
set_global_assignment -name VHDL_FILE ../../vhdl/fifo.vhd
set_global_assignment -name VHDL_FILE ../../vhdl/DRAM.vhd
set_global_assignment -name VHDL_FILE ../../vhdl/spimaster.vhd
set_global_assignment -name VHDL_FILE ../../vhdl/clkscale.vhd
set_global_assignment -name VHDL_FILE ../../vhdl/Z80cpu.vhd
set_global_assignment -name VHDL_FILE ../../vhdl/RAM4K36.vhd
set_global_assignment -name VHDL_FILE ../../vhdl/RAM4K9.vhd
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
# Assign Port to IOs

23
board/de0_nano/Makefile Normal file
View File

@ -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

View File

@ -56,26 +56,28 @@ 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_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
@ -199,4 +201,4 @@ if {$make_assignments} {
if {$need_to_close_project} {
project_close
}
}
}

23
board/de2/Makefile Normal file
View File

@ -0,0 +1,23 @@
DESIGN_NAME = de2
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

203
board/de2/de2.tcl Normal file
View File

@ -0,0 +1,203 @@
# 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.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"]} {
puts "Project de2 is not open"
set make_assignments 0
}
} else {
# Only open if not already open
if {[project_exists de2]} {
project_open -revision de2 de2
} else {
project_new -revision de2 de2
}
set need_to_close_project 1
}
# Make assignments
if {$make_assignments} {
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"
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/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_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_C25 -to serial_rx
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to serial_rx
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_AE23 -to leds[0]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to leds[0]
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_AB21 -to leds[2]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to leds[2]
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_AD22 -to leds[4]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to leds[4]
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_V4 -to SDRAM_ADDR[1]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[1]
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_W2 -to SDRAM_ADDR[3]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[3]
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_U6 -to SDRAM_ADDR[5]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[5]
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_U5 -to SDRAM_ADDR[7]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[7]
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_W3 -to SDRAM_ADDR[9]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[9]
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_V5 -to SDRAM_ADDR[11]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_ADDR[11]
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_AA2 -to SDRAM_DQ[1]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[1]
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_Y3 -to SDRAM_DQ[3]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[3]
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_R8 -to SDRAM_DQ[5]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[5]
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_V7 -to SDRAM_DQ[7]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[7]
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_AB2 -to SDRAM_DQ[9]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[9]
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_AA4 -to SDRAM_DQ[11]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[11]
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_AC2 -to SDRAM_DQ[13]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[13]
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_AA5 -to SDRAM_DQ[15]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQ[15]
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_Y5 -to SDRAM_DQM[1]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_DQM[1]
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_AE3 -to SDRAM_BA[1]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_BA[1]
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_AA6 -to SDRAM_CKE
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_CKE
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_AB4 -to SDRAM_nRAS
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SDRAM_nRAS
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_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"
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
}
}

23
board/de2_70/Makefile Normal file
View File

@ -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

204
board/de2_70/de2_70.tcl Normal file
View File

@ -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
}
}

View File

@ -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;

View File

@ -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;

67
vhdl/RAM4K36.vhd Normal file
View File

@ -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;

184
vhdl/RAM4K9.vhd Normal file
View File

@ -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

View File

@ -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

View File

@ -15,6 +15,7 @@
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.T80_Pack.ALL;
entity top_level is
Port (

View File

@ -0,0 +1,472 @@
----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz>
--
-- 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;

View File

@ -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

View File

@ -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;

View File

@ -0,0 +1,474 @@
----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz>
--
-- 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;

429
vhdl/board/de2/pll_de2.vhd Normal file
View File

@ -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

View File

@ -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;

View File

@ -0,0 +1,473 @@
----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz>
--
-- 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;

View File

@ -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

View File

@ -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;