Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: enjoy-digital/litex
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: e76464167b14c367840cad42bed5acd3bf24bad0
Choose a base ref
...
head repository: enjoy-digital/litex
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 9fc488bdf670c69193a6fa14e5f0c218db8b0ffe
Choose a head ref
Loading
13 changes: 9 additions & 4 deletions litex/build/lattice/trellis.py
Original file line number Diff line number Diff line change
@@ -118,10 +118,10 @@ def nextpnr_ecp5_parse_device(device):
"yosys -l {build_name}.rpt {build_name}.ys",
"nextpnr-ecp5 --json {build_name}.json --lpf {build_name}.lpf --textcfg {build_name}.config \
--{architecture} --package {package} --speed {speed_grade} {timefailarg} {ignoreloops} --seed {seed}",
"ecppack {build_name}.config --svf {build_name}.svf --bit {build_name}.bit --bootaddr {bootaddr}"
"ecppack {build_name}.config --svf {build_name}.svf --bit {build_name}.bit --bootaddr {bootaddr} {spimode}"
]

def _build_script(source, build_template, build_name, architecture, package, speed_grade, timingstrict, ignoreloops, bootaddr, seed):
def _build_script(source, build_template, build_name, architecture, package, speed_grade, timingstrict, ignoreloops, bootaddr, seed, spimode):
if sys.platform in ("win32", "cygwin"):
script_ext = ".bat"
script_contents = "@echo off\nrem Autogenerated by LiteX / git: " + tools.get_litex_git_revision() + "\n\n"
@@ -142,7 +142,8 @@ def _build_script(source, build_template, build_name, architecture, package, spe
ignoreloops = "--ignore-loops" if ignoreloops else "",
bootaddr = bootaddr,
fail_stmt = fail_stmt,
seed = seed)
seed = seed,
spimode = "" if spimode is None else "--spimode {}".format(spimode))

script_file = "build_" + build_name + script_ext
tools.write_to_file(script_file, script_contents, force_unix=False)
@@ -190,6 +191,7 @@ def build(self, platform, fragment,
ignoreloops = False,
bootaddr = 0,
seed = 1,
spimode = None,
**kwargs):

# Create build directory
@@ -221,7 +223,7 @@ def build(self, platform, fragment,

# Generate build script
script = _build_script(False, self.build_template, build_name, architecture, package,
speed_grade, timingstrict, ignoreloops, bootaddr, seed)
speed_grade, timingstrict, ignoreloops, bootaddr, seed, spimode)
# Run
if run:
_run_script(script)
@@ -249,6 +251,8 @@ def trellis_args(parser):
help="ignore combinational loops in timing analysis, i.e. pass '--ignore-loops' to nextpnr")
parser.add_argument("--ecppack-bootaddr", default=0,
help="Set boot address for next image, i.e. pass '--bootaddr xxx' to ecppack")
parser.add_argument("--ecppack-spimode", default=None,
help="Set slave SPI programming mode")
parser.add_argument("--nextpnr-seed", default=1, type=int,
help="seed to pass to nextpnr")

@@ -258,5 +262,6 @@ def trellis_argdict(args):
"timingstrict": args.nextpnr_timingstrict,
"ignoreloops": args.nextpnr_ignoreloops,
"bootaddr": args.ecppack_bootaddr,
"spimode": args.ecppack_spimode,
"seed": args.nextpnr_seed,
}
12 changes: 6 additions & 6 deletions litex/build/xilinx/symbiflow.py
Original file line number Diff line number Diff line change
@@ -160,22 +160,22 @@ def _generate_makefile(self, platform, build_name):

Rule("all", ["$(TOP).bit"], phony=True),
Rule("$(TOP).eblif", ["$(VERILOG)", "$(MEM_INIT)", "$(XDC)"], commands=[
"synth -t $(TOP) -v $(VERILOG) -d $(BITSTREAM_DEVICE) -p $(PARTNAME) -x $(XDC) > /dev/null"
"symbiflow_synth -t $(TOP) -v $(VERILOG) -d $(BITSTREAM_DEVICE) -p $(PARTNAME) -x $(XDC) > /dev/null"
]),
Rule("$(TOP).net", ["$(TOP).eblif", "$(SDC)"], commands=[
"pack -e $(TOP).eblif -d $(DEVICE) -s $(SDC) > /dev/null"
"symbiflow_pack -e $(TOP).eblif -d $(DEVICE) -s $(SDC) > /dev/null"
]),
Rule("$(TOP).place", ["$(TOP).net", "$(PCF)"], commands=[
"place -e $(TOP).eblif -d $(DEVICE) -p $(PCF) -n $(TOP).net -P $(PARTNAME) -s $(SDC) > /dev/null"
"symbiflow_place -e $(TOP).eblif -d $(DEVICE) -p $(PCF) -n $(TOP).net -P $(PARTNAME) -s $(SDC) > /dev/null"
]),
Rule("$(TOP).route", ["$(TOP).place"], commands=[
"route -e $(TOP).eblif -d $(DEVICE) -s $(SDC) > /dev/null"
"symbiflow_route -e $(TOP).eblif -d $(DEVICE) -s $(SDC) > /dev/null"
]),
Rule("$(TOP).fasm", ["$(TOP).route"], commands=[
"write_fasm -e $(TOP).eblif -d $(DEVICE) > /dev/null"
"symbiflow_write_fasm -e $(TOP).eblif -d $(DEVICE) > /dev/null"
]),
Rule("$(TOP).bit", ["$(TOP).fasm"], commands=[
"write_bitstream -d $(BITSTREAM_DEVICE) -f $(TOP).fasm -p $(PARTNAME) -b $(TOP).bit > /dev/null"
"symbiflow_write_bitstream -d $(BITSTREAM_DEVICE) -f $(TOP).fasm -p $(PARTNAME) -b $(TOP).bit > /dev/null"
]),
Rule("clean", phony=True, commands=[
"rm -f $(ARTIFACTS)"
2 changes: 2 additions & 0 deletions litex/soc/cores/i2s.py
Original file line number Diff line number Diff line change
@@ -283,10 +283,12 @@ def __init__(self, pads, fifo_depth=256, controller=False, master=False, concate
o_WRERR = rx_wrerr,
)
self.comb += [ # Wire up the status signals and interrupts
self.rx_stat.fields.overflow.eq(rx_wrerr),
self.rx_stat.fields.underflow.eq(rx_rderr),
self.rx_stat.fields.dataready.eq(rx_almostfull),
self.rx_stat.fields.wrcount.eq(rx_wrcount),
self.rx_stat.fields.rdcount.eq(rx_rdcount),
self.rx_stat.fields.empty.eq(rx_empty),
self.ev.rx_ready.trigger.eq(rx_almostfull),
self.ev.rx_error.trigger.eq(rx_wrerr | rx_rderr),
]
93 changes: 49 additions & 44 deletions litex/soc/cores/spi.py
Original file line number Diff line number Diff line change
@@ -41,91 +41,96 @@ def __init__(self, pads, data_width, sys_clk_freq, spi_clk_freq, with_csr=True,

# # #

bits = Signal(8)
xfer = Signal()
shift = Signal()
clk_enable = Signal()
cs_enable = Signal()
count = Signal(max=data_width)
mosi_latch = Signal()
miso_latch = Signal()

# Clock generation -------------------------------------------------------------------------
clk_divider = Signal(16)
clk_rise = Signal()
clk_fall = Signal()
self.comb += clk_rise.eq(clk_divider == (self.clk_divider[1:] - 1))
self.comb += clk_fall.eq(clk_divider == (self.clk_divider - 1))
self.sync += [
If(clk_rise, pads.clk.eq(xfer)),
If(clk_fall, pads.clk.eq(0)),
If(clk_fall,
clk_divider.eq(0)
).Else(
clk_divider.eq(clk_divider + 1)
clk_divider.eq(clk_divider + 1),
If(clk_rise,
pads.clk.eq(clk_enable),
).Elif(clk_fall,
clk_divider.eq(0),
pads.clk.eq(0),
)
]
self.comb += clk_rise.eq(clk_divider == (self.clk_divider[1:] - 1))
self.comb += clk_fall.eq(clk_divider == (self.clk_divider - 1))

# Control FSM ------------------------------------------------------------------------------
self.submodules.fsm = fsm = FSM(reset_state="IDLE")
fsm.act("IDLE",
self.done.eq(1),
If(self.start,
NextValue(bits, 0),
NextState("WAIT-CLK-FALL")
self.done.eq(0),
mosi_latch.eq(1),
NextState("START")
)
)
fsm.act("WAIT-CLK-FALL",
fsm.act("START",
NextValue(count, 0),
If(clk_fall,
NextState("XFER")
cs_enable.eq(1),
NextState("RUN")
)
)
fsm.act("XFER",
If(bits == self.length,
NextState("END")
).Elif(clk_fall,
NextValue(bits, bits + 1)
),
xfer.eq(1),
shift.eq(1)
fsm.act("RUN",
clk_enable.eq(1),
cs_enable.eq(1),
If(clk_fall,
NextValue(count, count + 1),
If(count == (self.length - 1),
NextState("STOP")
)
)
)
fsm.act("END",
fsm.act("STOP",
cs_enable.eq(1),
If(clk_rise,
miso_latch.eq(1),
self.irq.eq(1),
NextState("IDLE")
),
shift.eq(1),
self.irq.eq(1)
)
)

# Chip Select generation -------------------------------------------------------------------
if hasattr(pads, "cs_n"):
for i in range(len(pads.cs_n)):
self.comb += pads.cs_n[i].eq(~self.cs[i] | ~xfer)
self.sync += pads.cs_n[i].eq(~self.cs[i] | ~cs_enable)

# Master Out Slave In (MOSI) generation (generated on spi_clk falling edge) ----------------
mosi_data = Array(self.mosi[i] for i in range(data_width))
mosi_bit = Signal(max=data_width)
mosi_data = Signal(data_width)
mosi_array = Array(mosi_data[i] for i in range(data_width))
mosi_sel = Signal(max=data_width)
self.sync += [
If(self.start,
mosi_bit.eq(self.length - 1 if mode == "aligned" else data_width - 1),
).Elif(clk_rise & shift,
mosi_bit.eq(mosi_bit - 1)
If(mosi_latch,
mosi_data.eq(self.mosi),
mosi_sel.eq((self.length-1) if mode == "aligned" else (data_width-1)),
).Elif(clk_fall,
If(cs_enable, pads.mosi.eq(mosi_array[mosi_sel])),
mosi_sel.eq(mosi_sel - 1)
),
If(clk_fall,
pads.mosi.eq(mosi_data[mosi_bit])
)
]

# Master In Slave Out (MISO) capture (captured on spi_clk rising edge) --------------------
miso = Signal()
miso_data = self.miso
miso_data = Signal(data_width)
self.sync += [
If(clk_rise & shift,
If(clk_rise,
If(self.loopback,
miso.eq(pads.mosi)
miso_data.eq(Cat(pads.mosi, miso_data))
).Else(
miso.eq(pads.miso)
miso_data.eq(Cat(pads.miso, miso_data))
)
),
If(clk_fall & shift,
miso_data.eq(Cat(miso, miso_data))
)
]
self.sync += If(miso_latch, self.miso.eq(miso_data))

def add_csr(self, with_cs=True, with_loopback=True):
self._control = CSRStorage(fields=[
52 changes: 40 additions & 12 deletions litex/soc/integration/soc.py
Original file line number Diff line number Diff line change
@@ -280,21 +280,49 @@ def check_region_is_io(self, region):
# Add Master/Slave -----------------------------------------------------------------------------
def add_adapter(self, name, interface, direction="m2s"):
assert direction in ["m2s", "s2m"]
if interface.data_width != self.data_width:
self.logger.info("{} Bus {} from {}-bit to {}-bit.".format(
colorer(name),
colorer("converted", color="cyan"),
colorer(interface.data_width),
colorer(self.data_width)))
new_interface = wishbone.Interface(data_width=self.data_width)

if isinstance(interface, wishbone.Interface):
if interface.data_width != self.data_width:
new_interface = wishbone.Interface(data_width=self.data_width)
if direction == "m2s":
converter = wishbone.Converter(master=interface, slave=new_interface)
if direction == "s2m":
converter = wishbone.Converter(master=new_interface, slave=interface)
self.submodules += converter
else:
new_interface = interface
elif isinstance(interface, axi.AXILiteInterface):
# Data width conversion
intermediate = axi.AXILiteInterface(data_width=self.data_width)
if direction == "m2s":
converter = wishbone.Converter(master=interface, slave=new_interface)
converter = axi.AXILiteConverter(master=interface, slave=intermediate)
if direction == "s2m":
converter = wishbone.Converter(master=new_interface, slave=interface)
converter = axi.AXILiteConverter(master=intermediate, slave=interface)
self.submodules += converter
# Bus type conversion
new_interface = wishbone.Interface(data_width=self.data_width)
if direction == "m2s":
converter = axi.AXILite2Wishbone(axi_lite=intermediate, wishbone=new_interface)
elif direction == "s2m":
converter = axi.Wishbone2AXILite(wishbone=new_interface, axi_lite=intermediate)
self.submodules += converter
return new_interface
else:
return interface
raise TypeError(interface)

fmt = "{name} Bus {converted} from {frombus} {frombits}-bit to {tobus} {tobits}-bit."
frombus = "Wishbone" if isinstance(interface, wishbone.Interface) else "AXILite"
tobus = "Wishbone" if isinstance(new_interface, wishbone.Interface) else "AXILite"
frombits = interface.data_width
tobits = new_interface.data_width
if frombus != tobus or frombits != tobits:
self.logger.info(fmt.format(
name = colorer(name),
converted = colorer("converted", color="cyan"),
frombus = colorer("Wishbone" if isinstance(interface, wishbone.Interface) else "AXILite"),
frombits = colorer(interface.data_width),
tobus = colorer("Wishbone" if isinstance(new_interface, wishbone.Interface) else "AXILite"),
tobits = colorer(new_interface.data_width)))
return new_interface

def add_master(self, name=None, master=None):
if name is None:
@@ -1238,7 +1266,7 @@ def add_spi_sdcard(self, name="spisdcard", spi_clk_freq=400e3):
pads = self.platform.request(name)
if hasattr(pads, "rst"):
self.comb += pads.rst.eq(0)
spisdcard = SPIMaster(pads, 32, self.sys_clk_freq, spi_clk_freq, mode="aligned")
spisdcard = SPIMaster(pads, 8, self.sys_clk_freq, spi_clk_freq)
spisdcard.add_clk_divider()
setattr(self.submodules, name, spisdcard)
self.add_csr(name)
Loading