parser.add_argument("-Op", "--platform-option", default=[], nargs=2, action="append", help="set platform-specific option")
parser.add_argument("-X", "--external", default="", help="use external directory for targets, platforms and imports")
parser.add_argument("--csr_csv", default="csr.csv", help="CSV file to save the CSR map into")
-
+
parser.add_argument("-d", "--decorate", default=[], action="append", help="apply simplification decorator to top-level")
parser.add_argument("-Ob", "--build-option", default=[], nargs=2, action="append", help="set build option")
parser.add_argument("-f", "--flash-proxy-dir", default=None, help="set search directory for flash proxy bitstreams")
self._baddress = CSRStorage(flen(phase.bank))
self._wrdata = CSRStorage(flen(phase.wrdata))
self._rddata = CSRStatus(flen(phase.rddata))
-
+
###
self.comb += [
inti = dfi.Interface(a, ba, d, nphases)
self.slave = dfi.Interface(a, ba, d, nphases)
self.master = dfi.Interface(a, ba, d, nphases)
-
+
self._control = CSRStorage(4) # sel, cke, odt, reset_n
-
+
for n, phase in enumerate(inti.phases):
setattr(self.submodules, "pi" + str(n), PhaseInjector(phase))
-
+
###
-
+
self.comb += If(self._control.storage[0],
self.slave.connect(self.master)
).Else(
class Framebuffer(Module, AutoCSR):
def __init__(self, pads_vga, pads_dvi, lasmim):
pack_factor = lasmim.dw//bpp
-
+
g = DataFlowGraph()
self.fi = FrameInitiator(lasmim.aw, pack_factor)
cast = structuring.Cast(lasmim.dw, pixel_layout(pack_factor), reverse_to=True)
vtg = VTG(pack_factor)
self.driver = Driver(pack_factor, pads_vga, pads_dvi)
-
+
g.add_connection(self.fi, vtg, source_subr=self.fi.timing_subr, sink_ep="timing")
g.add_connection(dma_out, cast)
g.add_connection(cast, vtg, sink_ep="pixels")
self.comb += q_m8_n.eq((n1d > 4) | ((n1d == 4) & ~d[0]))
for i in range(8):
if i:
- curval = curval ^ d[i] ^ q_m8_n
+ curval = curval ^ d[i] ^ q_m8_n
else:
- curval = d[0]
+ curval = d[0]
self.sync += q_m[i].eq(curval)
self.sync += q_m[8].eq(~q_m8_n)
if __name__ == "__main__":
from migen.sim.generic import run_simulation
from random import Random
-
+
rng = Random(788)
test_list = [rng.randrange(256) for i in range(500)]
tb = _EncoderTB(test_list)
check = [_decode_tmds(out)[3] for out in tb.outs]
assert(check == test_list)
-
+
nb0 = 0
nb1 = 0
for out in tb.outs:
("hsync_start", hbits_dyn, 656, h_alignment_bits),
("hsync_end", hbits_dyn, 752, h_alignment_bits),
("hscan", hbits_dyn, 800, h_alignment_bits),
-
+
("vres", _vbits, 480),
("vsync_start", _vbits, 492),
("vsync_end", _vbits, 494),
hactive = Signal()
vactive = Signal()
active = Signal()
-
+
hcounter = Signal(hbits_dyn)
vcounter = Signal(_vbits)
-
+
skip = bpc - bpc_phy
self.comb += [
active.eq(hactive & vactive),
generate_frame_done.eq(0),
If(generate_en,
hcounter.eq(hcounter + 1),
-
+
If(hcounter == 0, hactive.eq(1)),
If(hcounter == tr.hres, hactive.eq(0)),
If(hcounter == tr.hsync_start, self.phy.payload.hsync.eq(1)),
vcounter.eq(vcounter + 1)
)
),
-
+
If(vcounter == 0, vactive.eq(1)),
If(vcounter == tr.vres, vactive.eq(0)),
If(vcounter == tr.vsync_start, self.phy.payload.vsync.eq(1)),
def __init__(self, pack_factor):
self.phy = Sink(phy_layout(pack_factor))
self.busy = Signal()
-
+
self.pix_hsync = Signal()
self.pix_vsync = Signal()
self.pix_de = Signal()
self.pix_r = Signal(bpc_phy)
self.pix_g = Signal(bpc_phy)
self.pix_b = Signal(bpc_phy)
-
+
###
fifo = RenameClockDomains(AsyncFIFO(phy_layout(pack_factor), 512),
self.specials += Instance("DCM_CLKGEN",
p_CLKFXDV_DIVIDE=2, p_CLKFX_DIVIDE=4, p_CLKFX_MD_MAX=1.0, p_CLKFX_MULTIPLY=2,
p_CLKIN_PERIOD=20.0, p_SPREAD_SPECTRUM="NONE", p_STARTUP_WAIT="FALSE",
-
+
i_CLKIN=ClockSignal("base50"), o_CLKFX=clk_pix_unbuffered,
i_PROGCLK=ClockSignal(), i_PROGDATA=pix_progdata, i_PROGEN=pix_progen,
o_PROGDONE=pix_progdone, o_LOCKED=pix_locked,
p_CLKOUT1_DIVIDE=5, # pix2x
p_CLKOUT2_DIVIDE=10, # pix
p_COMPENSATION="INTERNAL",
-
+
i_CLKINSEL=1,
i_CLKIN1=clk_pix_unbuffered,
o_CLKOUT0=pll_clk0, o_CLKOUT1=pll_clk1, o_CLKOUT2=pll_clk2,
o_CLKFBOUT=clkfbout, i_CLKFBIN=clkfbout,
- o_LOCKED=pll_locked,
+ o_LOCKED=pll_locked,
i_RST=~pix_locked | self._r_pll_reset.storage,
i_DADDR=self._r_pll_adr.storage,
# add CPU Verilog sources
if cpu_type == "lm32":
- platform.add_sources(os.path.join("verilog", "lm32", "submodule", "rtl"),
+ 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",
self._r_revision = CSRStatus(32)
self._r_frequency = CSRStatus(32)
self._r_l2_size = CSRStatus(8)
-
+
###
if revision is None:
read_latency=phy_settings.read_latency+1,
write_latency=phy_settings.write_latency+1)
self.nrowbits = geom_settings.col_a - address_align
-
+
###
self.submodules.refresher = Refresher(geom_settings.mux_a, geom_settings.bank_a,
def __init__(self, col_a, address_align):
self.col_a = col_a
self.address_align = address_align
-
+
def row(self, address):
split = self.col_a - self.address_align
if isinstance(address, int):
return address >> split
else:
return address[split:]
-
+
def col(self, address):
split = self.col_a - self.address_align
if isinstance(address, int):
return (address & (2**split - 1)) << self.address_align
else:
return Cat(Replicate(0, self.address_align), address[:split])
-
+
class BankMachine(Module):
def __init__(self, geom_settings, timing_settings, address_align, bankn, req):
self.refresh_req = Signal()
reqf = self.req_fifo.dout
slicer = _AddressSlicer(geom_settings.col_a, address_align)
-
+
# Row tracking
has_openrow = Signal()
openrow = Signal(geom_settings.row_a)
has_openrow.eq(0)
)
]
-
+
# Address generation
s_row_adr = Signal()
self.comb += [
self.cmd.a.eq(slicer.col(reqf.adr))
)
]
-
+
# Respect write-to-precharge specification
precharge_ok = Signal()
t_unsafe_precharge = 2 + timing_settings.tWR - 1
unsafe_precharge_count.eq(unsafe_precharge_count-1)
)
]
-
+
# Control and command generation FSM
fsm = FSM()
self.submodules += fsm
self.want_cmds = Signal()
# NB: cas_n/ras_n/we_n are 1 when stb is inactive
self.cmd = CommandRequestRW(flen(requests[0].a), flen(requests[0].ba))
-
+
###
rr = RoundRobin(len(requests), SP_CE)
self.submodules += rr
-
+
self.comb += [rr.request[i].eq(req.stb & ((req.is_cmd & self.want_cmds) | ((req.is_read == self.want_reads) | (req.is_write == self.want_writes))))
for i, req in enumerate(requests)]
-
+
stb = Signal()
self.comb += stb.eq(Array(req.stb for req in requests)[rr.grant])
for name in ["a", "ba", "is_read", "is_write", "is_cmd"]:
self.comb += self.cmd.stb.eq(stb \
& ((self.cmd.is_cmd & self.want_cmds) | ((self.cmd.is_read == self.want_reads) \
& (self.cmd.is_write == self.want_writes))))
-
+
self.comb += [If(self.cmd.stb & self.cmd.ack & (rr.grant == i), req.ack.eq(1))
for i, req in enumerate(requests)]
self.comb += rr.ce.eq(self.cmd.ack)
ncmd = len(commands)
nph = len(dfi.phases)
self.sel = [Signal(max=ncmd) for i in range(nph)]
-
+
###
-
+
def stb_and(cmd, attr):
if not hasattr(cmd, "stb"):
return 0
class Multiplexer(Module, AutoCSR):
def __init__(self, phy_settings, geom_settings, timing_settings, bank_machines, refresher, dfi, lasmic):
assert(phy_settings.nphases == len(dfi.phases))
-
+
# Command choosing
requests = [bm.cmd for bm in bank_machines]
choose_cmd = _CommandChooser(requests)
self.comb += [
choose_cmd.want_cmds.eq(1),
choose_req.want_cmds.eq(1)
- ]
+ ]
self.submodules += choose_cmd, choose_req
-
+
# Command steering
nop = CommandRequest(geom_settings.mux_a, geom_settings.bank_a)
commands = [nop, choose_cmd.cmd, choose_req.cmd, refresher.cmd] # nop must be 1st
(STEER_NOP, STEER_CMD, STEER_REQ, STEER_REFRESH) = range(4)
steerer = _Steerer(commands, dfi)
self.submodules += steerer
-
+
# Read/write turnaround
read_available = Signal()
write_available = Signal()
read_available.eq(optree("|", [req.stb & req.is_read for req in requests])),
write_available.eq(optree("|", [req.stb & req.is_write for req in requests]))
]
-
+
def anti_starvation(timeout):
en = Signal()
max_time = Signal()
return en, max_time
read_time_en, max_read_time = anti_starvation(timing_settings.read_time)
write_time_en, max_write_time = anti_starvation(timing_settings.write_time)
-
+
# Refresh
self.comb += [bm.refresh_req.eq(refresher.req) for bm in bank_machines]
go_to_refresh = Signal()
self.comb += go_to_refresh.eq(optree("&", [bm.refresh_gnt for bm in bank_machines]))
-
+
# Datapath
all_rddata = [p.rddata for p in dfi.phases]
all_wrdata = [p.wrdata for p in dfi.phases]
Cat(*all_wrdata).eq(lasmic.dat_w),
Cat(*all_wrdata_mask).eq(~lasmic.dat_we)
]
-
+
# Control FSM
fsm = FSM()
self.submodules += fsm
-
+
def steerer_sel(steerer, phy_settings, r_w_n):
r = []
for i in range(phy_settings.nphases):
self.req = Signal()
self.ack = Signal() # 1st command 1 cycle after assertion of ack
self.cmd = CommandRequest(a, ba)
-
+
###
# Refresh sequence generator:
seq_done.eq(1)
])
])
-
+
# Periodic refresh counter
counter = Signal(max=tREFI)
start = Signal()
counter.eq(counter - 1)
)
]
-
+
# Control FSM
fsm = FSM()
self.submodules += fsm
sdram_phy = lasmicon.PhySettings(
memtype="DDR",
- dfi_d=64,
+ dfi_d=64,
nphases=2,
rdphase=0,
wrphase=1,
tWTR=2,
tREFI=ns(7800, False),
tRFC=ns(70),
-
+
req_queue_size=8,
read_time=32,
write_time=16
self.cmd = cmd
if rw:
self.comb += self.cmd.ack.eq(1)
-
+
def do_simulation(self, selfp):
elts = ["@" + str(selfp.simulator.cycle_counter)]
cmdp = selfp.cmd
class DFILogger(Module):
def __init__(self, dfi):
self.dfi = dfi
-
+
def do_simulation(self, selfp):
dfip = selfp.dfi
for i, p in enumerate(dfip.phases):
self.ack = ack
self.state = 0
self.prng = Random(92837)
-
+
def do_simulation(self, selfp):
elts = ["@" + str(selfp.simulator.cycle_counter)]
-
+
if self.state == 0:
if selfp.req:
elts.append("Refresher requested access")
elts.append("Refresher released access")
selfp.ack = 0
self.state = 0
-
+
if len(elts) > 1:
print("\t".join(elts))
i_clk_i=ClockSignal(),
i_rst_i=ResetSignal(),
-
+
i_interrupt=self.interrupt,
-
+
o_I_ADR_O=i_adr_o,
o_I_DAT_O=i.dat_w,
o_I_SEL_O=i.sel,
i_I_ACK_I=i.ack,
i_I_ERR_I=i.err,
i_I_RTY_I=0,
-
+
o_D_ADR_O=d_adr_o,
o_D_DAT_O=d.dat_w,
o_D_SEL_O=d.sel,
self._rx_count_1 = CSRStatus(_count_width)
self._tx_count = CSRStorage(_count_width, write_from_dev=True)
self._tx_start = CSR()
-
+
self.submodules.ev = EventManager()
self.ev.rx0 = EventSourcePulse()
self.ev.rx1 = EventSourcePulse()
self.ev.tx = EventSourcePulse()
self.ev.finalize()
-
+
self.membus = wishbone.Interface()
-
+
###
init = Signal(reset=1)
rx_pending_1_r = Signal()
self.comb += [
pads.rst_n.eq(~self._phy_reset.storage),
-
+
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.dat_w.eq(0),
self._tx_count.we.eq(self.ev.tx.trigger)
]
Instance.Input("tx_start", self._tx_start.re),
Instance.Input("tx_count", self._tx_count.storage),
Instance.Output("tx_done", self.ev.tx.trigger),
-
+
Instance.Input("wb_adr_i", self.membus.adr),
Instance.Input("wb_dat_i", self.membus.dat_w),
Instance.Input("wb_sel_i", self.membus.sel),
Instance.Input("wb_we_i", self.membus.we),
Instance.Output("wb_dat_o", self.membus.dat_r),
Instance.Output("wb_ack_o", self.membus.ack),
-
+
Instance.Input("phy_tx_clk", ClockSignal("eth_tx")),
Instance.Output("phy_tx_data", pads.tx_data),
Instance.Output("phy_tx_en", pads.tx_en),
self.clk4x_rd_strb = Signal()
###
-
+
infreq = 50*1000000
ratio = Fraction(outfreq1x)/Fraction(infreq)
in_period = float(Fraction(1000000000)/Fraction(infreq))
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_sdram_half.clk),
#
-# 1:1 frequency-ratio Generic SDR PHY
-#
-# The GENSDRPHY is validated on CycloneIV (Altera) but since it does
+# 1:1 frequency-ratio Generic SDR PHY
+#
+# The GENSDRPHY is validated on CycloneIV (Altera) but since it does
# not use vendor-dependent code, it can also be used on other architectures.
#
# The PHY needs 2 Clock domains:
# - sys_clk : The System Clock domain
-# - sys_clk_ps : The System Clock domain with its phase shifted
+# - sys_clk_ps : The System Clock domain with its phase shifted
# (-3ns on C4@100MHz)
#
-# Assert dfi_wrdata_en and present the data
+# Assert dfi_wrdata_en and present the data
# on dfi_wrdata_mask/dfi_wrdata in the same
# cycle as the write command.
#
read_latency=4,
write_latency=0
)
-
+
self.dfi = Interface(a, ba, d)
###
- #
+ #
# Command/address
#
self.sync += [
self.sync.sys_ps += sd_dq_in_ps.eq(pads.dq)
self.sync += self.dfi.p0.rddata.eq(sd_dq_in_ps)
- #
+ #
# DQ/DM control
#
d_dfi_wrdata_en = Signal()
def get_sdram_phy_header(sdram_phy):
r = "#ifndef __GENERATED_SDRAM_PHY_H\n#define __GENERATED_SDRAM_PHY_H\n"
r += "#include <hw/common.h>\n#include <generated/csr.h>\n#include <hw/flags.h>\n\n"
-
+
nphases = sdram_phy.phy_settings.nphases
r += "#define DFII_NPHASES "+str(nphases)+"\n\n"
#define command_prd(X) command_p{rdphase}(X)
#define command_pwr(X) command_p{wrphase}(X)
-""".format(rdphase=str(sdram_phy.phy_settings.rdphase), wrphase=str(sdram_phy.phy_settings.wrphase))
+""".format(rdphase=str(sdram_phy.phy_settings.rdphase), wrphase=str(sdram_phy.phy_settings.wrphase))
r +="\n"
#
}
cl = sdram_phy.phy_settings.cl
-
+
if sdram_phy.phy_settings.memtype == "SDR":
bl = sdram_phy.phy_settings.nphases
mr = log2_int(bl) + (cl << 4)
bl = 2*sdram_phy.phy_settings.nphases
if bl != 8:
raise NotImplementedError("DDR3 PHY header generator only supports BL of 8")
-
+
def format_mr0(cl, wr, dll_reset):
cl_to_mr0 = {
5 : 0b0010,
# 1:2 frequency-ratio DDR / LPDDR / DDR2 PHY for Spartan-6
-#
-# Assert dfi_wrdata_en and present the data
+#
+# Assert dfi_wrdata_en and present the data
# on dfi_wrdata_mask/dfi_wrdata in the same
# cycle as the write command.
#
# Assert dfi_rddata_en in the same cycle as the read
# command. The data will come back on dfi_rddata
-# 5 cycles later, along with the assertion
+# 5 cycles later, along with the assertion
# of dfi_rddata_valid.
#
# This PHY only supports CAS Latency 3.
sdram_full_wr_clk = ClockSignal("sdram_full_wr")
sdram_full_rd_clk = ClockSignal("sdram_full_rd")
- #
+ #
# Command/address
#
if hasattr(pads, "cs_n"):
sd_sdram_half += pads.cs_n.eq(r_dfi[phase_sel].cs_n)
- #
+ #
# Bitslip
#
bitslip_cnt = Signal(4)
)
]
- #
+ #
# DQ/DQS/DM data
#
sdram_half_clk_n = Signal()
dqs_t_d0 = Signal()
dqs_t_d1 = Signal()
- dqs_o = Signal(d//8)
+ dqs_o = Signal(d//8)
dqs_t = Signal(d//8)
self.comb += [
sd_sdram_half += postamble.eq(drive_dqs)
- d_dfi = [Record(phase_wrdata_description(nphases*d)+phase_rddata_description(nphases*d))
+ d_dfi = [Record(phase_wrdata_description(nphases*d)+phase_rddata_description(nphases*d))
for i in range(2*nphases)]
for n, phase in enumerate(self.dfi.phases):
if hasattr(pads, "odt"):
self.comb += pads.odt.eq(0)
- #
+ #
# DQ/DQS/DM control
#
self.comb += drive_dq.eq(d_dfi[self.phy_settings.wrphase].wrdata_en)
d_dfi_wrdata_en = Signal()
sd_sys += d_dfi_wrdata_en.eq(d_dfi[self.phy_settings.wrphase].wrdata_en)
-
+
r_dfi_wrdata_en = Signal(2)
- sd_sdram_half += r_dfi_wrdata_en.eq(Cat(d_dfi_wrdata_en, r_dfi_wrdata_en[0]))
+ sd_sdram_half += r_dfi_wrdata_en.eq(Cat(d_dfi_wrdata_en, r_dfi_wrdata_en[0]))
self.comb += drive_dqs.eq(r_dfi_wrdata_en[1])
rddata_sr = Signal(self.phy_settings.read_latency)
sd_sys += rddata_sr.eq(Cat(rddata_sr[1:self.phy_settings.read_latency],
d_dfi[self.phy_settings.rdphase].rddata_en))
-
+
for n, phase in enumerate(self.dfi.phases):
self.comb += [
phase.rddata.eq(d_dfi[n].rddata),
self._en = CSRStorage()
self._update_value = CSR()
self._value = CSRStatus(width)
-
+
self.submodules.ev = EventManager()
self.ev.zero = EventSourceProcess()
self.ev.finalize()