+++ /dev/null
-RM ?= rm -f
-
-all: build/soc.bit build/soc.fpg
-
-build/soc.bit build/soc.bin:
- ./build.py
-
-build/soc.fpg: build/soc.bin
- $(MAKE) -C tools
- tools/byteswap $< $@
-
-load: build/soc.bit
- jtag -n load.jtag
-
-flash: build/soc.fpg
- m1nor-ng build/soc.fpg
-
-clean:
- $(RM) -r build/*
-
-.PHONY: all load clean flash
------------------------------
This is the next-generation Milkymist(tm) system-on-chip design,
-introducing two key innovations:
+introducing two key features:
* Built on the powerful Migen VLSI logic design system.
- * Increased system memory performance thanks to a new architecture
- (ASMI) containing a transaction-reordering and superscalar controller.
+ * Increased system memory performance thanks to LASMI.
-The Milkymist-NG SoC supports the Milkymist One board. Obtain yours at:
- http://milkymist.org
+This translates to more development productivity, better video resolution
+and quality, ease of designing complex hardware accelerators, and much
+more flexibility in hardware designs.
-Note that the -NG version is still experimental work in progress. For the
-production version of Milkymist SoC, visit:
- https://github.com/milkymist/milkymist
+The Milkymist-NG SoC supports the Mixxeo and the Milkymist One.
+Obtain yours at http://milkymist.org
[> Instructions (software)
--------------------------
https://github.com/milkymist/migen
Once this is done, build the bitstream with:
- make
-This will generate the build/soc.bit programming file.
-Use:
- make load
-to load it with UrJTAG.
+ ./make.py [-p <platform>] -l
+This will generate the build/soc-<platform>.bit programming file
+and load it with UrJTAG.
-The SoC expects a bootloader to be located in flash at 0x860000, just
-like the legacy SoC did. However, there is no binary compatibility and a
-new BIOS needs to be built and flashed for the -NG SoC.
+A new BIOS needs to be built and flashed for the -NG SoC.
Enjoy!
+++ /dev/null
-#!/usr/bin/env python3
-
-import os
-
-from mibuild.platforms import m1
-from mibuild.tools import write_to_file
-
-from milkymist import cif
-
-import top
-
-def main():
- platform = m1.Platform()
- soc = top.SoC(platform)
-
- platform.add_platform_command("""
-NET "{clk50}" TNM_NET = "GRPclk50";
-TIMESPEC "TSclk50" = PERIOD "GRPclk50" 20 ns HIGH 50%;
-""", clk50=platform.lookup_request("clk50"))
-
- platform.add_platform_command("""
-INST "m1crg/wr_bufpll" LOC = "BUFPLL_X0Y2";
-INST "m1crg/rd_bufpll" LOC = "BUFPLL_X0Y3";
-
-PIN "m1crg/bufg_x1.O" CLOCK_DEDICATED_ROUTE = FALSE;
-""")
-
- if hasattr(soc, "fb"):
- platform.add_platform_command("""
-NET "vga_clk" TNM_NET = "GRPvga_clk";
-NET "sys_clk" TNM_NET = "GRPsys_clk";
-TIMESPEC "TSise_sucks1" = FROM "GRPvga_clk" TO "GRPsys_clk" TIG;
-TIMESPEC "TSise_sucks2" = FROM "GRPsys_clk" TO "GRPvga_clk" TIG;
-""")
-
- if hasattr(soc, "minimac"):
- platform.add_platform_command("""
-NET "{phy_rx_clk}" TNM_NET = "GRPphy_rx_clk";
-NET "{phy_tx_clk}" TNM_NET = "GRPphy_tx_clk";
-TIMESPEC "TSphy_rx_clk" = PERIOD "GRPphy_rx_clk" 40 ns HIGH 50%;
-TIMESPEC "TSphy_tx_clk" = PERIOD "GRPphy_tx_clk" 40 ns HIGH 50%;
-TIMESPEC "TSphy_tx_clk_io" = FROM "GRPphy_tx_clk" TO "PADS" 10 ns;
-TIMESPEC "TSphy_rx_clk_io" = FROM "PADS" TO "GRPphy_rx_clk" 10 ns;
-""",
- phy_rx_clk=platform.lookup_request("eth_clocks").rx,
- phy_tx_clk=platform.lookup_request("eth_clocks").tx,)
-
- if hasattr(soc, "dvisampler0"):
- platform.add_platform_command("""
-NET "{dviclk0}" TNM_NET = "GRPdviclk0";
-NET "{dviclk0}" CLOCK_DEDICATED_ROUTE = FALSE;
-TIMESPEC "TSdviclk0" = PERIOD "GRPdviclk0" 26.7 ns HIGH 50%;
-""", dviclk0=platform.lookup_request("dvi_in", 0).clk)
- if hasattr(soc, "dvisampler1"):
- platform.add_platform_command("""
-NET "{dviclk1}" TNM_NET = "GRPdviclk1";
-NET "{dviclk1}" CLOCK_DEDICATED_ROUTE = FALSE;
-TIMESPEC "TSdviclk1" = PERIOD "GRPdviclk1" 26.7 ns HIGH 50%;
-""", dviclk1=platform.lookup_request("dvi_in", 1).clk)
-
- for d in ["m1crg", "s6ddrphy", "minimac3"]:
- platform.add_source_dir(os.path.join("verilog", d))
- platform.add_sources(os.path.join("verilog", "lm32", "submodule", "rtl"),
- "lm32_cpu.v", "lm32_instruction_unit.v", "lm32_decoder.v",
- "lm32_load_store_unit.v", "lm32_adder.v", "lm32_addsub.v", "lm32_logic_op.v",
- "lm32_shifter.v", "lm32_multiplier.v", "lm32_mc_arithmetic.v",
- "lm32_interrupt.v", "lm32_ram.v", "lm32_dp_ram.v", "lm32_icache.v",
- "lm32_dcache.v", "lm32_top.v", "lm32_debug.v", "lm32_jtag.v", "jtag_cores.v",
- "jtag_tap_spartan6.v", "lm32_itlb.v", "lm32_dtlb.v")
- platform.add_sources(os.path.join("verilog", "lm32"), "lm32_config.v")
-
- platform.build_cmdline(soc, build_name="soc")
- csr_header = cif.get_csr_header(soc.csr_base, soc.csrbankarray, soc.interrupt_map)
- write_to_file("software/include/hw/csr.h", csr_header)
-
-if __name__ == "__main__":
- main()
--- /dev/null
+import subprocess
+
+def load(bitstream):
+ cmds = """cable milkymist
+detect
+pld load {bitstream}
+quit
+""".format(bitstream=bitstream)
+ process = subprocess.Popen("jtag", stdin=subprocess.PIPE)
+ process.stdin.write(cmds.encode("ASCII"))
+ process.communicate()
+
+def flash(bitstream):
+ subprocess.call(["m1nor-ng", bitstream])
+++ /dev/null
-cable milkymist
-detect
-pld load build/soc.bit
--- /dev/null
+#!/usr/bin/env python3
+
+import argparse, os, importlib, subprocess
+
+from mibuild.tools import write_to_file
+
+from milkymist import cif
+import top, jtag
+
+def build(platform_name, build_bitstream, build_header):
+ platform_module = importlib.import_module("mibuild.platforms."+platform_name)
+ platform = platform_module.Platform()
+ soc = top.SoC(platform, platform_name)
+
+ platform.add_platform_command("""
+INST "mxcrg/wr_bufpll" LOC = "BUFPLL_X0Y2";
+INST "mxcrg/rd_bufpll" LOC = "BUFPLL_X0Y3";
+
+PIN "mxcrg/bufg_x1.O" CLOCK_DEDICATED_ROUTE = FALSE;
+""")
+
+ if hasattr(soc, "fb"):
+ platform.add_platform_command("""
+NET "vga_clk" TNM_NET = "GRPvga_clk";
+NET "sys_clk" TNM_NET = "GRPsys_clk";
+TIMESPEC "TSise_sucks1" = FROM "GRPvga_clk" TO "GRPsys_clk" TIG;
+TIMESPEC "TSise_sucks2" = FROM "GRPsys_clk" TO "GRPvga_clk" TIG;
+""")
+
+ for d in ["mxcrg", "s6ddrphy", "minimac3"]:
+ platform.add_source_dir(os.path.join("verilog", d))
+ platform.add_sources(os.path.join("verilog", "lm32", "submodule", "rtl"),
+ "lm32_cpu.v", "lm32_instruction_unit.v", "lm32_decoder.v",
+ "lm32_load_store_unit.v", "lm32_adder.v", "lm32_addsub.v", "lm32_logic_op.v",
+ "lm32_shifter.v", "lm32_multiplier.v", "lm32_mc_arithmetic.v",
+ "lm32_interrupt.v", "lm32_ram.v", "lm32_dp_ram.v", "lm32_icache.v",
+ "lm32_dcache.v", "lm32_top.v", "lm32_debug.v", "lm32_jtag.v", "jtag_cores.v",
+ "jtag_tap_spartan6.v", "lm32_itlb.v", "lm32_dtlb.v")
+ platform.add_sources(os.path.join("verilog", "lm32"), "lm32_config.v")
+
+ if build_bitstream:
+ build_name = "soc-"+platform_name
+ platform.build(soc, build_name=build_name)
+ subprocess.call(["tools/byteswap", build_name+".bin", build_name+".fpg"])
+ else:
+ soc.finalize()
+ if build_header:
+ csr_header = cif.get_csr_header(soc.csr_base, soc.csrbankarray, soc.interrupt_map)
+ write_to_file("software/include/hw/csr.h", csr_header)
+
+def main():
+ parser = argparse.ArgumentParser(description="milkymist-ng - a high performance SoC built on Migen technology.")
+ parser.add_argument("-p", "--platform", default="mixxeo", help="platform to build for")
+ parser.add_argument("-B", "--no-bitstream", default=False, action="store_true", help="do not build bitstream file")
+ parser.add_argument("-H", "--no-header", default=False, action="store_true", help="do not build C header file with CSR/IRQ defs")
+ parser.add_argument("-l", "--load", default=False, action="store_true", help="load bitstream to SRAM")
+ parser.add_argument("-f", "--flash", default=False, action="store_true", help="load bitstream to flash")
+ args = parser.parse_args()
+
+ build(args.platform, not args.no_bitstream, not args.no_header)
+ if args.load:
+ jtag.load("build/soc-"+args.platform+".bit")
+ if args.flash:
+ jtag.flash("build/soc-"+args.platform+".fpg")
+
+if __name__ == "__main__":
+ main()
+++ /dev/null
-from fractions import Fraction
-
-from migen.fhdl.std import *
-from migen.bank.description import *
-
-class M1CRG(Module, AutoCSR):
- def __init__(self, pads, outfreq1x):
- self.clock_domains.cd_sys = ClockDomain()
- self.clock_domains.cd_sys2x_270 = ClockDomain()
- self.clock_domains.cd_sys4x_wr = ClockDomain()
- self.clock_domains.cd_sys4x_rd = ClockDomain()
- self.clock_domains.cd_eth_rx = ClockDomain()
- self.clock_domains.cd_eth_tx = ClockDomain()
- self.clock_domains.cd_vga = ClockDomain(reset_less=True)
-
- self.clk4x_wr_strb = Signal()
- self.clk4x_rd_strb = Signal()
-
- self._r_cmd_data = CSRStorage(10)
- self._r_send_cmd_data = CSR()
- self._r_send_go = CSR()
- self._r_status = CSRStatus(3)
-
- ###
-
- infreq = 50*1000000
- ratio = Fraction(outfreq1x)/Fraction(infreq)
- in_period = float(Fraction(1000000000)/Fraction(infreq))
-
- vga_progdata = Signal()
- vga_progen = Signal()
- vga_progdone = Signal()
- vga_locked = Signal()
-
- self.specials += Instance("m1crg",
- Instance.Parameter("in_period", in_period),
- Instance.Parameter("f_mult", ratio.numerator),
- Instance.Parameter("f_div", ratio.denominator),
- Instance.Input("clk50_pad", pads.clk50),
- Instance.Input("trigger_reset", pads.trigger_reset),
-
- Instance.Input("eth_rx_clk_pad", pads.eth_rx_clk),
- Instance.Input("eth_tx_clk_pad", pads.eth_tx_clk),
-
- Instance.Output("sys_clk", self.cd_sys.clk),
- Instance.Output("sys_rst", self.cd_sys.rst),
- Instance.Output("clk2x_270", self.cd_sys2x_270.clk),
- Instance.Output("clk4x_wr", self.cd_sys4x_wr.clk),
- Instance.Output("clk4x_rd", self.cd_sys4x_rd.clk),
- Instance.Output("eth_rx_clk", self.cd_eth_rx.clk),
- Instance.Output("eth_tx_clk", self.cd_eth_tx.clk),
- Instance.Output("vga_clk", self.cd_vga.clk),
-
- Instance.Output("clk4x_wr_strb", self.clk4x_wr_strb),
- Instance.Output("clk4x_rd_strb", self.clk4x_rd_strb),
- Instance.Output("norflash_rst_n", pads.norflash_rst_n),
- Instance.Output("ddr_clk_pad_p", pads.ddr_clk_p),
- Instance.Output("ddr_clk_pad_n", pads.ddr_clk_n),
- Instance.Output("eth_phy_clk_pad", pads.eth_phy_clk),
- Instance.Output("vga_clk_pad", pads.vga_clk),
-
- Instance.Input("vga_progclk", ClockSignal()),
- Instance.Input("vga_progdata", vga_progdata),
- Instance.Input("vga_progen", vga_progen),
- Instance.Output("vga_progdone", vga_progdone),
- Instance.Output("vga_locked", vga_locked))
-
- remaining_bits = Signal(max=11)
- transmitting = Signal()
- self.comb += transmitting.eq(remaining_bits != 0)
- sr = Signal(10)
- self.sync += [
- If(self._r_send_cmd_data.re,
- remaining_bits.eq(10),
- sr.eq(self._r_cmd_data.storage)
- ).Elif(transmitting,
- remaining_bits.eq(remaining_bits - 1),
- sr.eq(sr[1:])
- )
- ]
- self.comb += [
- vga_progdata.eq(transmitting & sr[0]),
- vga_progen.eq(transmitting | self._r_send_go.re)
- ]
-
- # enforce gap between commands
- busy_counter = Signal(max=14)
- busy = Signal()
- self.comb += busy.eq(busy_counter != 0)
- self.sync += If(self._r_send_cmd_data.re,
- busy_counter.eq(13)
- ).Elif(busy,
- busy_counter.eq(busy_counter - 1)
- )
-
- self.comb += self._r_status.status.eq(Cat(busy, vga_progdone, vga_locked))
--- /dev/null
+from fractions import Fraction
+
+from migen.fhdl.std import *
+from migen.bank.description import *
+
+class MXCRG(Module, AutoCSR):
+ def __init__(self, pads, outfreq1x):
+ self.clock_domains.cd_sys = ClockDomain()
+ self.clock_domains.cd_sys2x_270 = ClockDomain()
+ self.clock_domains.cd_sys4x_wr = ClockDomain()
+ self.clock_domains.cd_sys4x_rd = ClockDomain()
+ self.clock_domains.cd_eth_rx = ClockDomain()
+ self.clock_domains.cd_eth_tx = ClockDomain()
+ self.clock_domains.cd_vga = ClockDomain(reset_less=True)
+
+ self.clk4x_wr_strb = Signal()
+ self.clk4x_rd_strb = Signal()
+
+ self._r_cmd_data = CSRStorage(10)
+ self._r_send_cmd_data = CSR()
+ self._r_send_go = CSR()
+ self._r_status = CSRStatus(3)
+
+ ###
+
+ infreq = 50*1000000
+ ratio = Fraction(outfreq1x)/Fraction(infreq)
+ in_period = float(Fraction(1000000000)/Fraction(infreq))
+
+ vga_progdata = Signal()
+ vga_progen = Signal()
+ vga_progdone = Signal()
+ vga_locked = Signal()
+
+ self.specials += Instance("mxcrg",
+ Instance.Parameter("in_period", in_period),
+ Instance.Parameter("f_mult", ratio.numerator),
+ Instance.Parameter("f_div", ratio.denominator),
+ Instance.Input("clk50_pad", pads.clk50),
+ Instance.Input("trigger_reset", pads.trigger_reset),
+
+ Instance.Input("eth_rx_clk_pad", pads.eth_rx_clk),
+ Instance.Input("eth_tx_clk_pad", pads.eth_tx_clk),
+
+ Instance.Output("sys_clk", self.cd_sys.clk),
+ Instance.Output("sys_rst", self.cd_sys.rst),
+ Instance.Output("clk2x_270", self.cd_sys2x_270.clk),
+ Instance.Output("clk4x_wr", self.cd_sys4x_wr.clk),
+ Instance.Output("clk4x_rd", self.cd_sys4x_rd.clk),
+ Instance.Output("eth_rx_clk", self.cd_eth_rx.clk),
+ Instance.Output("eth_tx_clk", self.cd_eth_tx.clk),
+ Instance.Output("vga_clk", self.cd_vga.clk),
+
+ Instance.Output("clk4x_wr_strb", self.clk4x_wr_strb),
+ Instance.Output("clk4x_rd_strb", self.clk4x_rd_strb),
+ Instance.Output("norflash_rst_n", pads.norflash_rst_n),
+ Instance.Output("ddr_clk_pad_p", pads.ddr_clk_p),
+ Instance.Output("ddr_clk_pad_n", pads.ddr_clk_n),
+ Instance.Output("eth_phy_clk_pad", pads.eth_phy_clk),
+ Instance.Output("vga_clk_pad", pads.vga_clk),
+
+ Instance.Input("vga_progclk", ClockSignal()),
+ Instance.Input("vga_progdata", vga_progdata),
+ Instance.Input("vga_progen", vga_progen),
+ Instance.Output("vga_progdone", vga_progdone),
+ Instance.Output("vga_locked", vga_locked))
+
+ remaining_bits = Signal(max=11)
+ transmitting = Signal()
+ self.comb += transmitting.eq(remaining_bits != 0)
+ sr = Signal(10)
+ self.sync += [
+ If(self._r_send_cmd_data.re,
+ remaining_bits.eq(10),
+ sr.eq(self._r_cmd_data.storage)
+ ).Elif(transmitting,
+ remaining_bits.eq(remaining_bits - 1),
+ sr.eq(sr[1:])
+ )
+ ]
+ self.comb += [
+ vga_progdata.eq(transmitting & sr[0]),
+ vga_progen.eq(transmitting | self._r_send_go.re)
+ ]
+
+ # enforce gap between commands
+ busy_counter = Signal(max=14)
+ busy = Signal()
+ self.comb += busy.eq(busy_counter != 0)
+ self.sync += If(self._r_send_cmd_data.re,
+ busy_counter.eq(13)
+ ).Elif(busy,
+ busy_counter.eq(busy_counter - 1)
+ )
+
+ self.comb += self._r_status.status.eq(Cat(busy, vga_progdone, vga_locked))
from migen.bus import wishbone, csr, lasmibus, dfi
from migen.bus import wishbone2lasmi, wishbone2csr
from migen.bank import csrgen
+from mibuild.generic_platform import ConstraintError
-from milkymist import m1crg, lm32, norflash, uart, s6ddrphy, dfii, lasmicon, \
+from milkymist import mxcrg, lm32, norflash, uart, s6ddrphy, dfii, lasmicon, \
identifier, timer, minimac3, framebuffer, dvisampler, \
counteradc, gpio
from milkymist.cif import get_macros
write_time=16
)
-class M1ClockPads:
+class MXClockPads:
def __init__(self, platform):
self.clk50 = platform.request("clk50")
- self.trigger_reset = platform.request("user_btn", 1)
+ self.trigger_reset = 0
+ try:
+ self.trigger_reset = platform.request("user_btn", 1)
+ except ConstraintError:
+ pass
self.norflash_rst_n = platform.request("norflash_rst_n")
self.vga_clk = platform.request("vga_clock")
ddram_clock = platform.request("ddram_clock")
"dvisampler1": 4,
}
- def __init__(self, platform):
+ def __init__(self, platform, platform_name):
#
# LASMI
#
#
# CSR
#
- self.submodules.crg = m1crg.M1CRG(M1ClockPads(platform), clk_freq)
+ self.submodules.crg = mxcrg.MXCRG(MXClockPads(platform), clk_freq)
self.submodules.uart = uart.UART(platform.request("serial"), clk_freq, baud=115200)
self.submodules.identifier = identifier.Identifier(0x4D31, version, int(clk_freq))
self.submodules.timer0 = timer.Timer()
self.submodules.fb = framebuffer.MixFramebuffer(platform.request("vga"), lasmim_fb0, lasmim_fb1)
self.submodules.dvisampler0 = dvisampler.DVISampler(platform.request("dvi_in", 0), lasmim_dvi0)
self.submodules.dvisampler1 = dvisampler.DVISampler(platform.request("dvi_in", 1), lasmim_dvi1)
- pots_pads = platform.request("dvi_pots")
- self.submodules.pots = counteradc.CounterADC(pots_pads.charge,
- [pots_pads.blackout, pots_pads.crossfade])
- self.submodules.buttons = gpio.GPIOIn(Cat(platform.request("user_btn", 0), platform.request("user_btn", 2)))
- self.submodules.leds = gpio.GPIOOut(Cat(*[platform.request("user_led", i) for i in range(2)]))
+ if platform_name == "m1":
+ pots_pads = platform.request("dvi_pots")
+ self.submodules.pots = counteradc.CounterADC(pots_pads.charge,
+ [pots_pads.blackout, pots_pads.crossfade])
+ self.submodules.buttons = gpio.GPIOIn(Cat(platform.request("user_btn", 0), platform.request("user_btn", 2)))
+ self.submodules.leds = gpio.GPIOOut(Cat(*[platform.request("user_led", i) for i in range(2)]))
self.submodules.csrbankarray = csrgen.BankArray(self,
lambda name, memory: self.csr_map[name if memory is None else name + "_" + memory.name_override])
+++ /dev/null
-module m1crg #(
- parameter in_period = 0.0,
- parameter f_mult = 0,
- parameter f_div = 0,
- parameter clk2x_period = (in_period*f_div)/(2.0*f_mult)
-) (
- input clk50_pad,
- input trigger_reset,
-
- output sys_clk,
- output reg sys_rst,
-
- /* Reset NOR flash */
- output norflash_rst_n,
-
- /* DDR PHY clocks */
- output clk2x_270,
- output clk4x_wr,
- output clk4x_wr_strb,
- output clk4x_rd,
- output clk4x_rd_strb,
-
- /* DDR off-chip clocking */
- output ddr_clk_pad_p,
- output ddr_clk_pad_n,
-
- /* Ethernet PHY clocks */
- output reg eth_phy_clk_pad,
- input eth_rx_clk_pad,
- input eth_tx_clk_pad,
- output eth_rx_clk,
- output eth_tx_clk,
-
- /* VGA clock */
- output vga_clk, /* < buffered, to internal clock network */
- output vga_clk_pad, /* < forwarded through ODDR2, to I/O */
-
- /* VGA clock control */
- input vga_progclk,
- input vga_progdata,
- input vga_progen,
- output vga_progdone,
- output vga_locked
-);
-
-/*
- * Reset
- */
-
-reg [19:0] rst_debounce;
-always @(posedge sys_clk) begin
- if(trigger_reset)
- rst_debounce <= 20'hFFFFF;
- else if(rst_debounce != 20'd0)
- rst_debounce <= rst_debounce - 20'd1;
- sys_rst <= rst_debounce != 20'd0;
-end
-
-/*
- * We must release the Flash reset before the system reset
- * because the Flash needs some time to come out of reset
- * and the CPU begins fetching instructions from it
- * as soon as the system reset is released.
- * From datasheet, minimum reset pulse width is 100ns
- * and reset-to-read time is 150ns.
- */
-
-reg [7:0] flash_rstcounter;
-
-always @(posedge sys_clk) begin
- if(trigger_reset)
- flash_rstcounter <= 8'd0;
- else if(~flash_rstcounter[7])
- flash_rstcounter <= flash_rstcounter + 8'd1;
-end
-
-assign norflash_rst_n = flash_rstcounter[7];
-
-/*
- * Clock management. Inspired by the NWL reference design.
- */
-
-wire sdr_clk50;
-wire clkdiv;
-
-IBUF #(
- .IOSTANDARD("DEFAULT")
-) clk2_iob (
- .I(clk50_pad),
- .O(sdr_clk50)
-);
-
-BUFIO2 #(
- .DIVIDE(1),
- .DIVIDE_BYPASS("FALSE"),
- .I_INVERT("FALSE")
-) bufio2_inst2 (
- .I(sdr_clk50),
- .IOCLK(),
- .DIVCLK(clkdiv),
- .SERDESSTROBE()
-);
-
-wire pll_lckd;
-wire buf_pll_fb_out;
-wire pllout0;
-wire pllout1;
-wire pllout2;
-wire pllout3;
-wire pllout4;
-wire pllout5;
-
-PLL_ADV #(
- .BANDWIDTH("OPTIMIZED"),
- .CLKFBOUT_MULT(4*f_mult),
- .CLKFBOUT_PHASE(0.0),
- .CLKIN1_PERIOD(in_period),
- .CLKIN2_PERIOD(in_period),
-
- .CLKOUT0_DIVIDE(f_div),
- .CLKOUT0_DUTY_CYCLE(0.5),
- .CLKOUT0_PHASE(0.0),
-
- .CLKOUT1_DIVIDE(f_div),
- .CLKOUT1_DUTY_CYCLE(0.5),
- .CLKOUT1_PHASE(0.0),
-
- .CLKOUT2_DIVIDE(2*f_div),
- .CLKOUT2_DUTY_CYCLE(0.5),
- .CLKOUT2_PHASE(270.0),
-
- .CLKOUT3_DIVIDE(4*f_div),
- .CLKOUT3_DUTY_CYCLE(0.5),
- .CLKOUT3_PHASE(0.0),
-
- .CLKOUT4_DIVIDE(4*f_mult),
- .CLKOUT4_DUTY_CYCLE(0.5),
- .CLKOUT4_PHASE(0.0),
-
- .CLKOUT5_DIVIDE(2*f_div),
- .CLKOUT5_DUTY_CYCLE(0.5),
- .CLKOUT5_PHASE(250.0),
-
- .COMPENSATION("INTERNAL"),
- .DIVCLK_DIVIDE(1),
- .REF_JITTER(0.100),
- .CLK_FEEDBACK("CLKFBOUT"),
- .SIM_DEVICE("SPARTAN6")
-) pll (
- .CLKFBDCM(),
- .CLKFBOUT(buf_pll_fb_out),
- .CLKOUT0(pllout0), /* < x4 clock for writes */
- .CLKOUT1(pllout1), /* < x4 clock for reads */
- .CLKOUT2(pllout2), /* < x2 270 clock for DQS, memory address and control signals */
- .CLKOUT3(pllout3), /* < x1 clock for system and memory controller */
- .CLKOUT4(pllout4), /* < buffered clk50 */
- .CLKOUT5(pllout5), /* < x2 clock to off-chip DDR */
- .CLKOUTDCM0(),
- .CLKOUTDCM1(),
- .CLKOUTDCM2(),
- .CLKOUTDCM3(),
- .CLKOUTDCM4(),
- .CLKOUTDCM5(),
- .DO(),
- .DRDY(),
- .LOCKED(pll_lckd),
- .CLKFBIN(buf_pll_fb_out),
- .CLKIN1(clkdiv),
- .CLKIN2(1'b0),
- .CLKINSEL(1'b1),
- .DADDR(5'b00000),
- .DCLK(1'b0),
- .DEN(1'b0),
- .DI(16'h0000),
- .DWE(1'b0),
- .RST(1'b0),
- .REL(1'b0)
-);
-
-BUFPLL #(
- .DIVIDE(4)
-) wr_bufpll (
- .PLLIN(pllout0),
- .GCLK(sys_clk),
- .LOCKED(pll_lckd),
- .IOCLK(clk4x_wr),
- .LOCK(),
- .SERDESSTROBE(clk4x_wr_strb)
-);
-
-BUFPLL #(
- .DIVIDE(4)
-) rd_bufpll (
- .PLLIN(pllout1),
- .GCLK(sys_clk),
- .LOCKED(pll_lckd),
- .IOCLK(clk4x_rd),
- .LOCK(),
- .SERDESSTROBE(clk4x_rd_strb)
-);
-
-BUFG bufg_x2_2(
- .I(pllout2),
- .O(clk2x_270)
-);
-
-BUFG bufg_x1(
- .I(pllout3),
- .O(sys_clk)
-);
-
-wire clk50g;
-BUFG bufg_50(
- .I(pllout4),
- .O(clk50g)
-);
-
-wire clk2x_off;
-BUFG bufg_x2_offclk(
- .I(pllout5),
- .O(clk2x_off)
-);
-
-
-/*
- * SDRAM clock
- */
-
-ODDR2 #(
- .DDR_ALIGNMENT("NONE"),
- .INIT(1'b0),
- .SRTYPE("SYNC")
-) sd_clk_forward_p (
- .Q(ddr_clk_pad_p),
- .C0(clk2x_off),
- .C1(~clk2x_off),
- .CE(1'b1),
- .D0(1'b1),
- .D1(1'b0),
- .R(1'b0),
- .S(1'b0)
-);
-ODDR2 #(
- .DDR_ALIGNMENT("NONE"),
- .INIT(1'b0),
- .SRTYPE("SYNC")
-) sd_clk_forward_n (
- .Q(ddr_clk_pad_n),
- .C0(clk2x_off),
- .C1(~clk2x_off),
- .CE(1'b1),
- .D0(1'b0),
- .D1(1'b1),
- .R(1'b0),
- .S(1'b0)
-);
-
-/*
- * Ethernet PHY
- */
-
-always @(posedge clk50g)
- eth_phy_clk_pad <= ~eth_phy_clk_pad;
-
-/* Let the synthesizer insert the appropriate buffers */
-assign eth_rx_clk = eth_rx_clk_pad;
-assign eth_tx_clk = eth_tx_clk_pad;
-
-/*
- * VGA clock
- */
-
-DCM_CLKGEN #(
- .CLKFXDV_DIVIDE(2),
- .CLKFX_DIVIDE(4),
- .CLKFX_MD_MAX(3.0),
- .CLKFX_MULTIPLY(2),
- .CLKIN_PERIOD(20.0),
- .SPREAD_SPECTRUM("NONE"),
- .STARTUP_WAIT("FALSE")
-) vga_clock_gen (
- .CLKFX(vga_clk),
- .CLKFX180(),
- .CLKFXDV(),
- .STATUS(),
- .CLKIN(clk50g),
- .FREEZEDCM(1'b0),
- .PROGCLK(vga_progclk),
- .PROGDATA(vga_progdata),
- .PROGEN(vga_progen),
- .PROGDONE(vga_progdone),
- .LOCKED(vga_locked),
- .RST(~pll_lckd | sys_rst)
-);
-
-ODDR2 #(
- .DDR_ALIGNMENT("NONE"),
- .INIT(1'b0),
- .SRTYPE("SYNC")
-) vga_clock_forward (
- .Q(vga_clk_pad),
- .C0(vga_clk),
- .C1(~vga_clk),
- .CE(1'b1),
- .D0(1'b1),
- .D1(1'b0),
- .R(1'b0),
- .S(1'b0)
-);
-
-endmodule
--- /dev/null
+module mxcrg #(
+ parameter in_period = 0.0,
+ parameter f_mult = 0,
+ parameter f_div = 0,
+ parameter clk2x_period = (in_period*f_div)/(2.0*f_mult)
+) (
+ input clk50_pad,
+ input trigger_reset,
+
+ output sys_clk,
+ output reg sys_rst,
+
+ /* Reset NOR flash */
+ output norflash_rst_n,
+
+ /* DDR PHY clocks */
+ output clk2x_270,
+ output clk4x_wr,
+ output clk4x_wr_strb,
+ output clk4x_rd,
+ output clk4x_rd_strb,
+
+ /* DDR off-chip clocking */
+ output ddr_clk_pad_p,
+ output ddr_clk_pad_n,
+
+ /* Ethernet PHY clocks */
+ output reg eth_phy_clk_pad,
+ input eth_rx_clk_pad,
+ input eth_tx_clk_pad,
+ output eth_rx_clk,
+ output eth_tx_clk,
+
+ /* VGA clock */
+ output vga_clk, /* < buffered, to internal clock network */
+ output vga_clk_pad, /* < forwarded through ODDR2, to I/O */
+
+ /* VGA clock control */
+ input vga_progclk,
+ input vga_progdata,
+ input vga_progen,
+ output vga_progdone,
+ output vga_locked
+);
+
+/*
+ * Reset
+ */
+
+reg [19:0] rst_debounce;
+always @(posedge sys_clk) begin
+ if(trigger_reset)
+ rst_debounce <= 20'hFFFFF;
+ else if(rst_debounce != 20'd0)
+ rst_debounce <= rst_debounce - 20'd1;
+ sys_rst <= rst_debounce != 20'd0;
+end
+
+initial rst_debounce <= 20'hFFFFF;
+
+/*
+ * We must release the Flash reset before the system reset
+ * because the Flash needs some time to come out of reset
+ * and the CPU begins fetching instructions from it
+ * as soon as the system reset is released.
+ * From datasheet, minimum reset pulse width is 100ns
+ * and reset-to-read time is 150ns.
+ */
+
+reg [7:0] flash_rstcounter;
+
+always @(posedge sys_clk) begin
+ if(trigger_reset)
+ flash_rstcounter <= 8'd0;
+ else if(~flash_rstcounter[7])
+ flash_rstcounter <= flash_rstcounter + 8'd1;
+end
+
+initial flash_rstcounter <= 8'd0;
+
+assign norflash_rst_n = flash_rstcounter[7];
+
+/*
+ * Clock management. Inspired by the NWL reference design.
+ */
+
+wire sdr_clk50;
+wire clkdiv;
+
+IBUF #(
+ .IOSTANDARD("DEFAULT")
+) clk2_iob (
+ .I(clk50_pad),
+ .O(sdr_clk50)
+);
+
+BUFIO2 #(
+ .DIVIDE(1),
+ .DIVIDE_BYPASS("FALSE"),
+ .I_INVERT("FALSE")
+) bufio2_inst2 (
+ .I(sdr_clk50),
+ .IOCLK(),
+ .DIVCLK(clkdiv),
+ .SERDESSTROBE()
+);
+
+wire pll_lckd;
+wire buf_pll_fb_out;
+wire pllout0;
+wire pllout1;
+wire pllout2;
+wire pllout3;
+wire pllout4;
+wire pllout5;
+
+PLL_ADV #(
+ .BANDWIDTH("OPTIMIZED"),
+ .CLKFBOUT_MULT(4*f_mult),
+ .CLKFBOUT_PHASE(0.0),
+ .CLKIN1_PERIOD(in_period),
+ .CLKIN2_PERIOD(in_period),
+
+ .CLKOUT0_DIVIDE(f_div),
+ .CLKOUT0_DUTY_CYCLE(0.5),
+ .CLKOUT0_PHASE(0.0),
+
+ .CLKOUT1_DIVIDE(f_div),
+ .CLKOUT1_DUTY_CYCLE(0.5),
+ .CLKOUT1_PHASE(0.0),
+
+ .CLKOUT2_DIVIDE(2*f_div),
+ .CLKOUT2_DUTY_CYCLE(0.5),
+ .CLKOUT2_PHASE(270.0),
+
+ .CLKOUT3_DIVIDE(4*f_div),
+ .CLKOUT3_DUTY_CYCLE(0.5),
+ .CLKOUT3_PHASE(0.0),
+
+ .CLKOUT4_DIVIDE(4*f_mult),
+ .CLKOUT4_DUTY_CYCLE(0.5),
+ .CLKOUT4_PHASE(0.0),
+
+ .CLKOUT5_DIVIDE(2*f_div),
+ .CLKOUT5_DUTY_CYCLE(0.5),
+ .CLKOUT5_PHASE(250.0),
+
+ .COMPENSATION("INTERNAL"),
+ .DIVCLK_DIVIDE(1),
+ .REF_JITTER(0.100),
+ .CLK_FEEDBACK("CLKFBOUT"),
+ .SIM_DEVICE("SPARTAN6")
+) pll (
+ .CLKFBDCM(),
+ .CLKFBOUT(buf_pll_fb_out),
+ .CLKOUT0(pllout0), /* < x4 clock for writes */
+ .CLKOUT1(pllout1), /* < x4 clock for reads */
+ .CLKOUT2(pllout2), /* < x2 270 clock for DQS, memory address and control signals */
+ .CLKOUT3(pllout3), /* < x1 clock for system and memory controller */
+ .CLKOUT4(pllout4), /* < buffered clk50 */
+ .CLKOUT5(pllout5), /* < x2 clock to off-chip DDR */
+ .CLKOUTDCM0(),
+ .CLKOUTDCM1(),
+ .CLKOUTDCM2(),
+ .CLKOUTDCM3(),
+ .CLKOUTDCM4(),
+ .CLKOUTDCM5(),
+ .DO(),
+ .DRDY(),
+ .LOCKED(pll_lckd),
+ .CLKFBIN(buf_pll_fb_out),
+ .CLKIN1(clkdiv),
+ .CLKIN2(1'b0),
+ .CLKINSEL(1'b1),
+ .DADDR(5'b00000),
+ .DCLK(1'b0),
+ .DEN(1'b0),
+ .DI(16'h0000),
+ .DWE(1'b0),
+ .RST(1'b0),
+ .REL(1'b0)
+);
+
+BUFPLL #(
+ .DIVIDE(4)
+) wr_bufpll (
+ .PLLIN(pllout0),
+ .GCLK(sys_clk),
+ .LOCKED(pll_lckd),
+ .IOCLK(clk4x_wr),
+ .LOCK(),
+ .SERDESSTROBE(clk4x_wr_strb)
+);
+
+BUFPLL #(
+ .DIVIDE(4)
+) rd_bufpll (
+ .PLLIN(pllout1),
+ .GCLK(sys_clk),
+ .LOCKED(pll_lckd),
+ .IOCLK(clk4x_rd),
+ .LOCK(),
+ .SERDESSTROBE(clk4x_rd_strb)
+);
+
+BUFG bufg_x2_2(
+ .I(pllout2),
+ .O(clk2x_270)
+);
+
+BUFG bufg_x1(
+ .I(pllout3),
+ .O(sys_clk)
+);
+
+wire clk50g;
+BUFG bufg_50(
+ .I(pllout4),
+ .O(clk50g)
+);
+
+wire clk2x_off;
+BUFG bufg_x2_offclk(
+ .I(pllout5),
+ .O(clk2x_off)
+);
+
+
+/*
+ * SDRAM clock
+ */
+
+ODDR2 #(
+ .DDR_ALIGNMENT("NONE"),
+ .INIT(1'b0),
+ .SRTYPE("SYNC")
+) sd_clk_forward_p (
+ .Q(ddr_clk_pad_p),
+ .C0(clk2x_off),
+ .C1(~clk2x_off),
+ .CE(1'b1),
+ .D0(1'b1),
+ .D1(1'b0),
+ .R(1'b0),
+ .S(1'b0)
+);
+ODDR2 #(
+ .DDR_ALIGNMENT("NONE"),
+ .INIT(1'b0),
+ .SRTYPE("SYNC")
+) sd_clk_forward_n (
+ .Q(ddr_clk_pad_n),
+ .C0(clk2x_off),
+ .C1(~clk2x_off),
+ .CE(1'b1),
+ .D0(1'b0),
+ .D1(1'b1),
+ .R(1'b0),
+ .S(1'b0)
+);
+
+/*
+ * Ethernet PHY
+ */
+
+always @(posedge clk50g)
+ eth_phy_clk_pad <= ~eth_phy_clk_pad;
+
+/* Let the synthesizer insert the appropriate buffers */
+assign eth_rx_clk = eth_rx_clk_pad;
+assign eth_tx_clk = eth_tx_clk_pad;
+
+/*
+ * VGA clock
+ */
+
+DCM_CLKGEN #(
+ .CLKFXDV_DIVIDE(2),
+ .CLKFX_DIVIDE(4),
+ .CLKFX_MD_MAX(3.0),
+ .CLKFX_MULTIPLY(2),
+ .CLKIN_PERIOD(20.0),
+ .SPREAD_SPECTRUM("NONE"),
+ .STARTUP_WAIT("FALSE")
+) vga_clock_gen (
+ .CLKFX(vga_clk),
+ .CLKFX180(),
+ .CLKFXDV(),
+ .STATUS(),
+ .CLKIN(clk50g),
+ .FREEZEDCM(1'b0),
+ .PROGCLK(vga_progclk),
+ .PROGDATA(vga_progdata),
+ .PROGEN(vga_progen),
+ .PROGDONE(vga_progdone),
+ .LOCKED(vga_locked),
+ .RST(~pll_lckd | sys_rst)
+);
+
+ODDR2 #(
+ .DDR_ALIGNMENT("NONE"),
+ .INIT(1'b0),
+ .SRTYPE("SYNC")
+) vga_clock_forward (
+ .Q(vga_clk_pad),
+ .C0(vga_clk),
+ .C1(~vga_clk),
+ .CE(1'b1),
+ .D0(1'b1),
+ .D1(1'b0),
+ .R(1'b0),
+ .S(1'b0)
+);
+
+endmodule