From 1578c74895e9da783a8a57697721346269bc4c49 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Sun, 9 Sep 2012 21:18:09 +0200 Subject: [PATCH] Initialize de0_nano example --- examples/de0_nano/Makefile | 18 +++++ examples/de0_nano/build.py | 45 +++++++++++ examples/de0_nano/build/.keep_me | 0 examples/de0_nano/constraints.py | 89 ++++++++++++++++++++++ examples/de0_nano/soc.qpf | 30 ++++++++ examples/de0_nano/timings.py | 29 ++++++++ examples/de0_nano/top.py | 123 +++++++++++++++++++++++++++++++ 7 files changed, 334 insertions(+) create mode 100644 examples/de0_nano/Makefile create mode 100644 examples/de0_nano/build.py create mode 100644 examples/de0_nano/build/.keep_me create mode 100644 examples/de0_nano/constraints.py create mode 100644 examples/de0_nano/soc.qpf create mode 100644 examples/de0_nano/timings.py create mode 100644 examples/de0_nano/top.py diff --git a/examples/de0_nano/Makefile b/examples/de0_nano/Makefile new file mode 100644 index 000000000..11ded926c --- /dev/null +++ b/examples/de0_nano/Makefile @@ -0,0 +1,18 @@ +PYTHON= + +all: build/soc.map + +# We need to change to the build directory because the Quartus tools +# tend to dump a mess of various files in the current directory. + +build/soc.qsf: + $(PYTHON) build.py + +build/soc.map: build/soc.qsf + cp soc.qpf build/soc.qpf + cd build && quartus_map soc.qpf + +clean: + rm -rf build/* + +.PHONY: load clean diff --git a/examples/de0_nano/build.py b/examples/de0_nano/build.py new file mode 100644 index 000000000..29510eea1 --- /dev/null +++ b/examples/de0_nano/build.py @@ -0,0 +1,45 @@ +import os +import top + +# list Verilog sources before changing directory +verilog_sources = [] +def add_core_dir(d): + root = os.path.join("verilog", d, "rtl") + files = os.listdir(root) + for f in files: + if f[-2:] == ".v": + verilog_sources.append(os.path.join(root, f)) +def add_core_files(d, files): + for f in files: + verilog_sources.append(os.path.join("verilog", d, f)) + +def get_qsf_prj(): + r = "" + for s in verilog_sources: + r += "set_global_assignment -name VERILOG_FILE " + s + "\n" + return r + +add_core_dir("generic") +add_core_dir("lm32") +add_core_dir("hpdmc_sdr16") +add_core_dir("fmlbrg") +add_core_dir("uart") +add_core_dir("rc5") +add_core_dir("gpio") +add_core_dir("spi_master") + +os.chdir("build") + +def str2file(filename, contents): + f = open(filename, "w") + f.write(contents) + f.close() + +# generate top +(src_verilog, qsf_cst) = top.get() +str2file("soc.v", src_verilog) +verilog_sources.append("build/soc.v") + +# generate Quartus project file +qsf_prj = get_qsf_prj() +str2file("soc.qsf", qsf_prj + qsf_cst) \ No newline at end of file diff --git a/examples/de0_nano/build/.keep_me b/examples/de0_nano/build/.keep_me new file mode 100644 index 000000000..e69de29bb diff --git a/examples/de0_nano/constraints.py b/examples/de0_nano/constraints.py new file mode 100644 index 000000000..4c46bc5e1 --- /dev/null +++ b/examples/de0_nano/constraints.py @@ -0,0 +1,89 @@ +class Constraints: + def __init__(self, uart0, rc50, gpio0, led0, sw0, spi_master0, hpdmc0): + self.constraints = [] + def add(signal, pin, vec=-1, iostandard="3.3-V LVTTL", extra="", sch=""): + self.constraints.append((signal, vec, pin, iostandard, extra,sch)) + def add_vec(signal, pins, iostandard="3.3-V LVTTL", extra="", sch=""): + assert(signal.bv.width == len(pins)), "%s size : %d / qsf size : %d" %(signal,signal.bv.width,len(pins)) + i = 0 + for p in pins: + add(signal, p, i, iostandard, extra) + i += 1 + + # uart0 + #add(uart0.tx, "TBD") + #add(uart0.rx, "TBD") + + # rc50 + #add(rc50.rx, "TBD") + + # gpio0 + #add_vec(gpio0.inputs, ["TBD","TBD","TBD","TBD", + # "TBD","TBD","TBD","TBD"]) + #add_vec(gpio0.outputs, ["TBD","TBD","TBD","TBD", + # "TBD","TBD","TBD","TBD"]) + + # led0 + add_vec(led0.outputs, ["A15", "A13", "B13", "A11", + "D1" , "F3" , "B1" , "L3"]) + + # sw0 + add_vec(sw0.inputs, ["M1", "T8", "B9", "M15"]) + + # spi_master0 + add(spi_master0.cs, "TBD") + add(spi_master0.sck, "TBD") + add(spi_master0.mosi, "TBD") + add(spi_master0.miso, "TBD") + + # hpdmc0 + add(hpdmc0.sdram_clk, "R4") + add(hpdmc0.sdram_cke, "L7") + add(hpdmc0.sdram_cs_n, "P6") + add(hpdmc0.sdram_we_n, "C2") + add(hpdmc0.sdram_cas_n, "L1") + add(hpdmc0.sdram_ras_n, "L2") + add_vec(hpdmc0.sdram_addr, ["P2","N5","N6","M8", + "P8","T7","N8","T6", + "R1","P1","N2","N1", + "L4",]) + add_vec(hpdmc0.sdram_ba, ["M7","M6"]) + add_vec(hpdmc0.sdram_dqm, ["R6","T5"]) + add_vec(hpdmc0.sdram_dq, ["G2", "G1", "L8", "K5", + "K2", "J2", "J1", "R7", + "T4", "T2", "T3", "R3", + "R5", "P3", "N3", "K1"]) + + def get_ios(self): + return set([c[0] for c in self.constraints]) + + def get_qsf(self, ns): + r = "" + for c in self.constraints: + r += "set_location_assignment PIN_"+str(c[2]) + r += " -to " + ns.get_name(c[0]) + if c[1] >= 0: + r += "[" + str(c[1]) + "]" + r += "\n" + + r += "set_instance_assignment -name IO_STANDARD " + r += "\"" + c[3] + "\"" + r += " -to " + ns.get_name(c[0]) + if c[1] >= 0: + r += "[" + str(c[1]) + "]" + r += "\n" + + r += """ +set_global_assignment -name FAMILY "Cyclone IV E" +set_global_assignment -name DEVICE EP4CE22F17C6 +set_global_assignment -name TOP_LEVEL_ENTITY "soc" +set_global_assignment -name DEVICE_FILTER_PACKAGE FPGA +set_global_assignment -name DEVICE_FILTER_PIN_COUNT 256 +set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 6 +set_global_assignment -name CYCLONEII_RESERVE_NCEO_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_FLASH_NCE_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_DATA0_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_DATA1_AFTER_CONFIGURATION "USE AS REGULAR IO" +set_global_assignment -name RESERVE_DCLK_AFTER_CONFIGURATION "USE AS REGULAR IO" + """ + return r diff --git a/examples/de0_nano/soc.qpf b/examples/de0_nano/soc.qpf new file mode 100644 index 000000000..82d96c173 --- /dev/null +++ b/examples/de0_nano/soc.qpf @@ -0,0 +1,30 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 1991-2009 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 +# Version 9.0 Build 132 02/25/2009 SJ Full Version +# Date created = 11:09:38 March 18, 2009 +# +# -------------------------------------------------------------------------- # + +QUARTUS_VERSION = "9.0" +DATE = "11:09:38 March 18, 2009" + +# Revisions + +PROJECT_REVISION = "soc" diff --git a/examples/de0_nano/timings.py b/examples/de0_nano/timings.py new file mode 100644 index 000000000..c3fa4b170 --- /dev/null +++ b/examples/de0_nano/timings.py @@ -0,0 +1,29 @@ +from math import ceil + +Hz = 1 +KHz = 10**3 +MHz = 10**6 +GHz = 10**9 + +s = 1 +ms = 1/KHz +us = 1/MHz +ns = 1/GHz + +class t2n: + def __init__(self, clk_period_ns): + self.clk_period_ns = clk_period_ns + self.clk_period_us = clk_period_ns*(GHz/MHz) + self.clk_period_ms = clk_period_ns*(GHz/KHz) + def ns(self,t,margin=True): + if margin: + t += self.clk_period_ns/2 + return ceil(t/self.clk_period_ns) + def us(self,t,margin=True): + if margin: + t += self.clk_period_us/2 + return ceil(t/self.clk_period_us) + def ms(self,t,margin=True): + if margin: + t += self.clk_period_ms/2 + return ceil(t/self.clk_period_ms) \ No newline at end of file diff --git a/examples/de0_nano/top.py b/examples/de0_nano/top.py new file mode 100644 index 000000000..033143a63 --- /dev/null +++ b/examples/de0_nano/top.py @@ -0,0 +1,123 @@ +# De0Nano-System On Chip / Generic Base for a Custom SOC +# - Lm32 SoftCore +# - 32MB Sdram +# - 2KB Eeprom (TBD) +# - G Sensor & AD Converter (TBD) +# - Up to 72 GPIO (8 in/ 8 out) +# - Uart +# - Spi Slave & Master (Only Master) + +#============================================================================== +# I M P O R T +#============================================================================== +from fractions import Fraction +from math import ceil + +from migen.fhdl.structure import * +from migen.fhdl import verilog, autofragment +from migen.bus import wishbone, csr, wishbone2csr, fml + +from soc import lm32, uart, rc5, gpio, spi_master, identifier, fmlbrg, hpdmc_sdr16 +from cmacros import get_macros +from timings import * +from constraints import Constraints + +#============================================================================== +# P A R A M E T E R S +#============================================================================== + +#Timings Param +clk_freq = 50*MHz +clk_period_ns = clk_freq*ns +n = t2n(clk_period_ns) + +#============================================================================== +# S O C +#============================================================================== + +# +# Configuration +#=============================================================================== + +# Csr +csr_macros = get_macros("common/csrbase.h") +def csr_offset(name): + base = int(csr_macros[name + "_BASE"], 0) + assert((base >= 0xe0000000) and (base <= 0xe0010000)) + return (base - 0xe0000000)//0x800 + +# Interrupt +interrupt_macros = get_macros("common/interrupt.h") +def interrupt_n(name): + return int(interrupt_macros[name + "_INTERRUPT"], 0) + +# Version +version = get_macros("common/version.h")["VERSION"][1:-1] + +def get(): + + # + # Wishbone + #=============================================================================== + cpu0 = lm32.LM32() + wishbone2csr0 = wishbone2csr.WB2CSR() + fmlbrg0 = fmlbrg.FMLBRG(16) + hpdmc0 = hpdmc_sdr16.HPDMC_SDR16(13) + + # CSR 0x00000000 (shadow @0x80000000) + # FML bridge 0x10000000 (shadow @0x90000000) + wishbonecon = wishbone.InterconnectShared( + [ + cpu0.ibus, + cpu0.dbus + ], [ + (binc("000") , wishbone2csr0.wishbone), + (binc("001") , fmlbrg0.wishbone) + ], + register=True, + offset=1) + # + # Fml + #=============================================================================== + fmlcon0 = fml.Interconnect(fmlbrg0.fml,hpdmc0.fml) + + # + # Csr + #=============================================================================== + uart0 = uart.UART(csr_offset("UART"), clk_freq, baud=115200) + identifier0 = identifier.Identifier(csr_offset("ID"), 0x1234, version, int(clk_freq)) + rc50 = rc5.RC5(csr_offset("RC5"),clk_freq) + gpio0 = gpio.GPIO(csr_offset("GPIO")) + led0 = gpio.GPIO(csr_offset("LED")) + sw0 = gpio.GPIO(csr_offset("SW"),4) + spi_master0 = spi_master.SPI_MASTER(csr_offset("SPI_MASTER")) + csrcon0 = csr.Interconnect(wishbone2csr0.csr, [ + uart0.csr, + identifier0.bank.interface, + rc50.csr, + gpio0.csr, + led0.csr, + sw0.csr, + spi_master0.csr, + hpdmc0.csr + ]) + + # + # Interrupts + #=============================================================================== + interrupts = Fragment([ + cpu0.interrupt[interrupt_n("UART")].eq(uart0.irq), + cpu0.interrupt[interrupt_n("RC5")].eq(rc50.irq), + cpu0.interrupt[interrupt_n("GPIO")].eq(gpio0.irq) + ]) + # + # HouseKeeping + #=============================================================================== + frag = autofragment.from_local() + interrupts + cst = Constraints(uart0, rc50, gpio0, led0, sw0, spi_master0, hpdmc0) + src_verilog, vns = verilog.convert(frag, + cst.get_ios(), + name="soc", + return_ns=True) + src_qsf = cst.get_qsf(vns) + return (src_verilog, src_qsf) \ No newline at end of file