diff --git a/build.py b/build.py index 661114f73..5e1f007b2 100644 --- a/build.py +++ b/build.py @@ -10,6 +10,7 @@ def add_core_dir(d): def add_core_files(d, files): for f in files: verilog_sources.append(os.path.join("verilog", d, f)) +add_core_dir("m1reset") add_core_files("lm32", ["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_spartan6.v", "lm32_mc_arithmetic.v", diff --git a/constraints.py b/constraints.py index 12eba657f..8ffd501d7 100644 --- a/constraints.py +++ b/constraints.py @@ -1,4 +1,4 @@ -def get(ns, norflash0, uart0): +def get(ns, reset0, norflash0, uart0): constraints = [] def add(signal, pin, vec=-1, iostandard="LVCMOS33", extra=""): constraints.append((ns.get_name(signal), vec, pin, iostandard, extra)) @@ -8,6 +8,11 @@ def get(ns, norflash0, uart0): add(signal, p, i, iostandard, extra) i += 1 + add(reset0.trigger_reset, "AA4") + add(reset0.ac97_rst_n, "D6") + add(reset0.videoin_rst_n, "W17") + add(reset0.flash_rst_n, "P22", extra="SLEW = FAST | DRIVE = 8") + add_vec(norflash0.adr, ["L22", "L20", "K22", "K21", "J19", "H20", "F22", "F21", "K17", "J17", "E22", "E20", "H18", "H19", "F20", "G19", "C22", "C20", "D22", "D21", "F19", "F18", "D20", "D19"], @@ -18,7 +23,6 @@ def get(ns, norflash0, uart0): add(norflash0.oe_n, "M22", extra="SLEW = FAST | DRIVE = 8") add(norflash0.we_n, "N20", extra="SLEW = FAST | DRIVE = 8") add(norflash0.ce_n, "M21", extra="SLEW = FAST | DRIVE = 8") - add(norflash0.rst_n, "P22", extra="SLEW = FAST | DRIVE = 8") add(uart0.tx, "L17", extra="SLEW = SLOW") add(uart0.rx, "K18", extra="PULLUP") @@ -38,8 +42,6 @@ def get(ns, norflash0, uart0): NET "sys_clk" LOC = AB11 | IOSTANDARD = LVCMOS33; NET "sys_clk" TNM_NET = "GRPclk50"; TIMESPEC "TSclk50" = PERIOD "GRPclk50" 20 ns HIGH 50%; - -NET "sys_rst" LOC = AA4 | IOSTANDARD = LVCMOS33; """ return r diff --git a/milkymist/m1reset/__init__.py b/milkymist/m1reset/__init__.py new file mode 100644 index 000000000..bfc3421e7 --- /dev/null +++ b/milkymist/m1reset/__init__.py @@ -0,0 +1,23 @@ +from functools import partial + +from migen.fhdl.structure import * + +class Inst: + def __init__(self): + d = partial(declare_signal, self) + d("trigger_reset") + d("sys_rst") + d("ac97_rst_n") + d("videoin_rst_n") + d("flash_rst_n") + self._inst = Instance("m1reset", + [("sys_rst", self.sys_rst), + ("ac97_rst_n", self.ac97_rst_n), + ("videoin_rst_n", self.videoin_rst_n), + ("flash_rst_n", self.flash_rst_n)], + [("trigger_reset", self.trigger_reset)], + clkport="sys_clk") + + def get_fragment(self): + return Fragment(instances=[self._inst], + pads={self.ac97_rst_n, self.videoin_rst_n, self.flash_rst_n}) diff --git a/milkymist/norflash/__init__.py b/milkymist/norflash/__init__.py index 55ffa6ea5..99b6c12df 100644 --- a/milkymist/norflash/__init__.py +++ b/milkymist/norflash/__init__.py @@ -13,7 +13,6 @@ class Inst: d("oe_n") d("we_n") d("ce_n") - d("rst_n") self.timeline = timeline.Inst(self.bus.cyc_i & self.bus.stb_i, [(0, [self.adr.eq(Cat(0, self.bus.adr_i[2:adr_width]))]), (rd_timing, [ @@ -27,6 +26,6 @@ class Inst: def get_fragment(self): comb = [self.oe_n.eq(0), self.we_n.eq(1), - self.ce_n.eq(0), self.rst_n.eq(1)] - return Fragment(comb, pads={self.adr, self.d, self.oe_n, self.we_n, self.ce_n, self.rst_n}) \ + self.ce_n.eq(0)] + return Fragment(comb, pads={self.adr, self.d, self.oe_n, self.we_n, self.ce_n}) \ + self.timeline.get_fragment() diff --git a/top.py b/top.py index f91cb75d5..75e8f70de 100644 --- a/top.py +++ b/top.py @@ -1,10 +1,13 @@ +from migen.fhdl.structure import * from migen.fhdl import convtools, verilog, autofragment from migen.bus import wishbone, csr, wishbone2csr -from milkymist import lm32, norflash, uart +from milkymist import m1reset, lm32, norflash, uart import constraints def get(): + reset0 = m1reset.Inst() + cpu0 = lm32.Inst() norflash0 = norflash.Inst(25, 12) wishbone2csr0 = wishbone2csr.Inst() @@ -16,8 +19,10 @@ def get(): uart0 = uart.Inst(0, 50*1000*1000, baud=115200) csrcon0 = csr.Interconnect(wishbone2csr0.csr, [uart0.bus]) - frag = autofragment.from_local() + frag = autofragment.from_local() + Fragment(pads={reset0.trigger_reset}) vns = convtools.Namespace() - src_verilog = verilog.Convert(frag, name="soc", ns=vns) - src_ucf = constraints.get(vns, norflash0, uart0) + src_verilog = verilog.Convert(frag, name="soc", + rst_signal=reset0.sys_rst, + ns=vns) + src_ucf = constraints.get(vns, reset0, norflash0, uart0) return (src_verilog, src_ucf) diff --git a/verilog/m1reset/m1reset.v b/verilog/m1reset/m1reset.v new file mode 100644 index 000000000..4095e4618 --- /dev/null +++ b/verilog/m1reset/m1reset.v @@ -0,0 +1,62 @@ +/* + * Milkymist-NG SoC + * Copyright (C) 2007, 2008, 2009, 2010, 2011 Sebastien Bourdeauducq + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +module m1reset( + input sys_clk, + input trigger_reset, + + output reg sys_rst, + output ac97_rst_n, + output videoin_rst_n, + output flash_rst_n +); + +reg [19:0] rst_debounce; +initial rst_debounce <= 20'hFFFFF; +initial sys_rst <= 1'b1; +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 + +assign ac97_rst_n = ~sys_rst; +assign videoin_rst_n = ~sys_rst; + +/* + * 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; +initial flash_rstcounter <= 8'd0; +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 flash_rst_n = flash_rstcounter[7]; + +endmodule