Skip to content
Permalink
Browse files
Add Ethernet MAC
  • Loading branch information
Sebastien Bourdeauducq committed May 19, 2012
1 parent 7d18736 commit 4e18e456864a0a37b684e088bd33876ccfbf89c8
@@ -12,6 +12,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("generic")
add_core_dir("m1crg")
add_core_dir("s6ddrphy")
add_core_files("lm32", ["lm32_cpu.v", "lm32_instruction_unit.v", "lm32_decoder.v",
@@ -20,6 +21,7 @@ def add_core_files(d, files):
"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"])
add_core_dir("minimac3")

os.chdir("build")

@@ -4,5 +4,6 @@
#define UART_BASE 0xe0000000
#define DFII_BASE 0xe0000800
#define ID_BASE 0xe0001000
#define MINIMAC_BASE 0xe0001800

#endif /* __CSRBASE_H */
@@ -1,5 +1,5 @@
class Constraints:
def __init__(self, crg0, norflash0, uart0, ddrphy0):
def __init__(self, crg0, norflash0, uart0, ddrphy0, minimac0):
self.constraints = []
def add(signal, pin, vec=-1, iostandard="LVCMOS33", extra=""):
self.constraints.append((signal, vec, pin, iostandard, extra))
@@ -15,6 +15,7 @@ def add_vec(signal, pins, iostandard="LVCMOS33", extra=""):
add(crg0.videoin_rst_n, "W17")
add(crg0.flash_rst_n, "P22", extra="SLEW = FAST | DRIVE = 8")
add(crg0.trigger_reset, "AA4")
add(crg0.phy_clk, "M20")

add_vec(norflash0.adr, ["L22", "L20", "K22", "K21", "J19", "H20", "F22",
"F21", "K17", "J17", "E22", "E20", "H18", "H19", "F20",
@@ -47,6 +48,21 @@ def add_vec(signal, pins, iostandard="LVCMOS33", extra=""):
extra=ddrsettings)
add_vec(ddrphy0.sd_dm, ["E1", "E3", "F3", "G4"], extra=ddrsettings)
add_vec(ddrphy0.sd_dqs, ["F1", "F2", "H5", "H6"], extra=ddrsettings)

add(minimac0.phy_rst_n, "R22")
add(minimac0.phy_dv, "V21")
add(minimac0.phy_rx_clk, "H22")
add(minimac0.phy_rx_er, "V22")
add_vec(minimac0.phy_rx_data, ["U22", "U20", "T22", "T21"])
add(minimac0.phy_tx_en, "N19")
add(minimac0.phy_tx_clk, "H21")
add(minimac0.phy_tx_er, "M19")
add_vec(minimac0.phy_tx_data, ["M16", "L15", "P19", "P20"])
add(minimac0.phy_col, "W20")
add(minimac0.phy_crs, "W22")

self._phy_rx_clk = minimac0.phy_rx_clk
self._phy_tx_clk = minimac0.phy_tx_clk

def get_ios(self):
return set([c[0] for c in self.constraints])
@@ -69,6 +85,13 @@ def get_ucf(self, ns):
INST "m1crg/rd_bufpll" LOC = "BUFPLL_X0Y3";
PIN "m1crg/bufg_x1.O" CLOCK_DEDICATED_ROUTE = FALSE;
"""
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;
""".format(phy_rx_clk=ns.get_name(self._phy_rx_clk), phy_tx_clk=ns.get_name(self._phy_tx_clk))

return r
@@ -18,7 +18,8 @@ def __init__(self, infreq, outfreq1x):
"clk4x_wr",
"clk4x_wr_strb",
"clk4x_rd",
"clk4x_rd_strb"
"clk4x_rd_strb",
"phy_clk"
]:
s = Signal(name=name)
setattr(self, name, s)
@@ -0,0 +1,105 @@
from migen.fhdl.structure import *
from migen.bank.description import *
from migen.bank.eventmanager import *
from migen.bank import csrgen
from migen.bus import wishbone

_count_width = 11

class MiniMAC:
def __init__(self, address):
# PHY signals
self.phy_tx_clk = Signal()
self.phy_tx_data = Signal(BV(4))
self.phy_tx_en = Signal()
self.phy_tx_er = Signal()
self.phy_rx_clk = Signal()
self.phy_rx_data = Signal(BV(4))
self.phy_dv = Signal()
self.phy_rx_er = Signal()
self.phy_col = Signal()
self.phy_crs = Signal()
self.phy_rst_n = Signal()

# CPU interface
self._phy_reset = RegisterField("phy_reset", reset=1)
self._rx_count_0 = RegisterField("rx_count_0", _count_width, access_bus=READ_ONLY, access_dev=WRITE_ONLY)
self._rx_count_1 = RegisterField("rx_count_1", _count_width, access_bus=READ_ONLY, access_dev=WRITE_ONLY)
self._tx_count = RegisterField("tx_count", _count_width, access_dev=READ_WRITE)
regs = [self._phy_reset, self._rx_count_0, self._rx_count_1, self._tx_count]

self._rx_event_0 = EventSourcePulse()
self._rx_event_1 = EventSourcePulse()
self._tx_event = EventSourcePulse()
self.events = EventManager(self._rx_event_0, self._rx_event_1, self._tx_event)

self.bank = csrgen.Bank(regs + self.events.get_registers(), address=address)
self.membus = wishbone.Interface()

def get_fragment(self):
init = Signal(reset=1)
rx_ready_0 = Signal()
rx_ready_1 = Signal()
rx_pending_0 = self._rx_event_0.pending
rx_pending_1 = self._rx_event_1.pending
rx_pending_0_r = Signal()
rx_pending_1_r = Signal()
comb = [
self.phy_rst_n.eq(~self._phy_reset.field.r),

rx_ready_0.eq(init | (rx_pending_0_r & ~rx_pending_0)),
rx_ready_1.eq(init | (rx_pending_1_r & ~rx_pending_1)),

self._tx_count.field.w.eq(0),
self._tx_count.field.we.eq(self._tx_event.trigger)
]
sync = [
init.eq(0),
rx_pending_0_r.eq(rx_pending_0),
rx_pending_1_r.eq(rx_pending_1)
]
inst = [
Instance("minimac3",
[
("rx_done_0", self._rx_event_0.trigger),
("rx_count_0", self._rx_count_0.field.w),
("rx_done_1", self._rx_event_1.trigger),
("rx_count_1", self._rx_count_1.field.w),

("tx_done", self._tx_event.trigger),

("wb_dat_o", self.membus.dat_r),
("wb_ack_o", self.membus.ack),

("phy_tx_data", self.phy_tx_data),
("phy_tx_en", self.phy_tx_en),
("phy_tx_er", self.phy_tx_er),
], [
("rx_ready_0", rx_ready_0),
("rx_ready_1", rx_ready_1),

("tx_start", self._tx_count.re),
("tx_count", self._tx_count.field.r),

("wb_adr_i", self.membus.adr),
("wb_dat_i", self.membus.dat_w),
("wb_sel_i", self.membus.sel),
("wb_stb_i", self.membus.stb),
("wb_cyc_i", self.membus.cyc),
("wb_we_i", self.membus.we),

("phy_tx_clk", self.phy_tx_clk),
("phy_rx_clk", self.phy_rx_clk),
("phy_rx_data", self.phy_rx_data),
("phy_dv", self.phy_dv),
("phy_rx_er", self.phy_rx_er),
("phy_col", self.phy_col),
("phy_crs", self.phy_crs)
],
clkport="sys_clk",
rstport="sys_rst"
)
]
return Fragment(comb, sync, instances=inst) \
+ self.events.get_fragment() \
+ self.bank.get_fragment()
9 top.py
@@ -5,7 +5,7 @@
from migen.fhdl import verilog, autofragment
from migen.bus import wishbone, wishbone2asmi, csr, wishbone2csr, dfi

from milkymist import m1crg, lm32, norflash, uart, sram, s6ddrphy, dfii, asmicon, identifier
from milkymist import m1crg, lm32, norflash, uart, sram, s6ddrphy, dfii, asmicon, identifier, minimac3
from cmacros import get_macros
from constraints import Constraints

@@ -88,6 +88,7 @@ def get():
cpu0 = lm32.LM32()
norflash0 = norflash.NorFlash(25, 12)
sram0 = sram.SRAM(sram_size//4)
minimac0 = minimac3.MiniMAC(csr_offset("MINIMAC"))
wishbone2asmi0 = wishbone2asmi.WB2ASMI(l2_size//4, asmiport_wb)
wishbone2csr0 = wishbone2csr.WB2CSR()

@@ -104,6 +105,7 @@ def get():
], [
(binc("000"), norflash0.bus),
(binc("001"), sram0.bus),
(binc("011"), minimac0.membus),
(binc("10"), wishbone2asmi0.wishbone),
(binc("11"), wishbone2csr0.wishbone)
],
@@ -118,7 +120,8 @@ def get():
csrcon0 = csr.Interconnect(wishbone2csr0.csr, [
uart0.bank.interface,
dfii0.bank.interface,
identifier0.bank.interface
identifier0.bank.interface,
minimac0.bank.interface
])

#
@@ -134,7 +137,7 @@ def get():
crg0 = m1crg.M1CRG(50*MHz, clk_freq)

frag = autofragment.from_local() + interrupts + ddrphy_clocking(crg0, ddrphy0)
cst = Constraints(crg0, norflash0, uart0, ddrphy0)
cst = Constraints(crg0, norflash0, uart0, ddrphy0, minimac0)
src_verilog, vns = verilog.convert(frag,
cst.get_ios(),
name="soc",
@@ -0,0 +1,48 @@
/*
* Milkymist 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 <http://www.gnu.org/licenses/>.
*/

module psync(
input clk1,
input i,
input clk2,
output o
);

reg level;
always @(posedge clk1)
if(i)
level <= ~level;

reg level1;
reg level2;
reg level3;
always @(posedge clk2) begin
level1 <= level;
level2 <= level1;
level3 <= level2;
end

assign o = level2 ^ level3;

initial begin
level <= 1'b0;
level1 <= 1'b0;
level2 <= 1'b0;
level3 <= 1'b0;
end

endmodule
@@ -37,7 +37,10 @@ module m1crg #(
output clk4x_wr,
output clk4x_wr_strb,
output clk4x_rd,
output clk4x_rd_strb
output clk4x_rd_strb,

/* Ethernet PHY clock */
output reg phy_clk
);

/*
@@ -107,6 +110,7 @@ wire pllout0;
wire pllout1;
wire pllout2;
wire pllout3;
wire pllout4;

PLL_ADV #(
.BANDWIDTH("OPTIMIZED"),
@@ -126,7 +130,7 @@ PLL_ADV #(
.CLKOUT3_DIVIDE(4*f_div),
.CLKOUT3_DUTY_CYCLE(0.5),
.CLKOUT3_PHASE(0.0),
.CLKOUT4_DIVIDE(7),
.CLKOUT4_DIVIDE(4*f_mult),
.CLKOUT4_DUTY_CYCLE(0.5),
.CLKOUT4_PHASE(0),
.CLKOUT5_DIVIDE(7),
@@ -144,7 +148,7 @@ PLL_ADV #(
.CLKOUT1(pllout1), /* < x4 clock for reads */
.CLKOUT2(pllout2), /* < x2 90 clock to generate memory clock, clock DQS and memory address and control signals. */
.CLKOUT3(pllout3), /* < x1 clock for system and memory controller */
.CLKOUT4(),
.CLKOUT4(pllout4), /* < buffered clkin */
.CLKOUT5(),
.CLKOUTDCM0(),
.CLKOUTDCM1(),
@@ -199,5 +203,9 @@ BUFG bufg_x1(
.I(pllout3),
.O(sys_clk)
);

/* Ethernet PHY */
always @(posedge pllout4)
phy_clk <= ~phy_clk;

endmodule
Loading

0 comments on commit 4e18e45

Please sign in to comment.