Skip to content

Commit

Permalink
Add Ethernet MAC
Browse files Browse the repository at this point in the history
  • Loading branch information
Sebastien Bourdeauducq committed May 19, 2012
1 parent 7d18736 commit 4e18e45
Show file tree
Hide file tree
Showing 13 changed files with 863 additions and 9 deletions.
2 changes: 2 additions & 0 deletions build.py
Expand Up @@ -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",
Expand All @@ -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")

Expand Down
1 change: 1 addition & 0 deletions common/csrbase.h
Expand Up @@ -4,5 +4,6 @@
#define UART_BASE 0xe0000000
#define DFII_BASE 0xe0000800
#define ID_BASE 0xe0001000
#define MINIMAC_BASE 0xe0001800

#endif /* __CSRBASE_H */
27 changes: 25 additions & 2 deletions constraints.py
@@ -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))
Expand All @@ -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",
Expand Down Expand Up @@ -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])
Expand All @@ -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
3 changes: 2 additions & 1 deletion milkymist/m1crg/__init__.py
Expand Up @@ -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)
Expand Down
105 changes: 105 additions & 0 deletions milkymist/minimac3/__init__.py
@@ -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 changes: 6 additions & 3 deletions top.py
Expand Up @@ -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

Expand Down Expand Up @@ -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()

Expand All @@ -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)
],
Expand All @@ -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
])

#
Expand All @@ -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",
Expand Down
48 changes: 48 additions & 0 deletions verilog/generic/psync.v
@@ -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
14 changes: 11 additions & 3 deletions verilog/m1crg/m1crg.v
Expand Up @@ -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
);

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

PLL_ADV #(
.BANDWIDTH("OPTIMIZED"),
Expand All @@ -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),
Expand All @@ -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(),
Expand Down Expand Up @@ -199,5 +203,9 @@ BUFG bufg_x1(
.I(pllout3),
.O(sys_clk)
);

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

endmodule

0 comments on commit 4e18e45

Please sign in to comment.