gw: fix synthesis

Still unclear what exactly this fixes, I think mostly bugs in
migen/LiteX. Not sure if it's synthesizing the memory elements for the
sampler modules either.
This commit is contained in:
David Lenfesty 2023-06-03 11:44:17 -06:00
parent 32eeab2c66
commit 5b62dd300b
4 changed files with 27 additions and 20 deletions

View File

@ -27,7 +27,7 @@ from litedram.phy import GENSDRPHY, HalfRateGENSDRPHY
from liteeth.phy.ecp5rgmii import LiteEthPHYRGMII from liteeth.phy.ecp5rgmii import LiteEthPHYRGMII
from sampler import Sampler from sampler import SamplerController, Sampler
from litex.soc.integration.soc import SoCRegion from litex.soc.integration.soc import SoCRegion
from test import run_test, TestResult, skip_suite from test import run_test, TestResult, skip_suite
@ -143,11 +143,11 @@ class BaseSoC(SoCCore):
if with_video_framebuffer: if with_video_framebuffer:
self.add_video_framebuffer(phy=self.videophy, timings="800x600@60Hz", clock_domain="hdmi") self.add_video_framebuffer(phy=self.videophy, timings="800x600@60Hz", clock_domain="hdmi")
self.submodules.sampler = Sampler(platform.request("adc"), self.crg.cd_sample_clock.clk) #samplers = [Sampler(platform.request("adc", i)) for i in range(3)]
sampler_region = SoCRegion(origin=None, size=0x1000, cached=False) #self.submodules.sampler_controller = SamplerController(samplers, buffer_len=2048 * 10)
#self.add_wb_slave(0x9000_0000, self.sampler.bus, 0x1000) ### TODO better way to do this?
## TODO better way to do this? #sampler_region = SoCRegion(origin=None, size=0x4000, cached=False)
#self.bus.add_slave(name="sampler", slave=self.sampler.bus, region=sampler_region) #self.bus.add_slave(name="sampler", slave=self.sampler_controller.bus, region=sampler_region)
# Build -------------------------------------------------------------------------------------------- # Build --------------------------------------------------------------------------------------------
@ -200,8 +200,9 @@ def main():
print(f"{passed}/{passed + failed} passed ({skipped} skipped)") print(f"{passed}/{passed + failed} passed ({skipped} skipped)")
# TODO maybe don't do this? if failed > 0 or not args.build:
return # Don't also build after this
return
# Build firmware # Build firmware
import subprocess as sp import subprocess as sp

View File

@ -175,9 +175,7 @@ _io_v7_2 = copy.deepcopy(_io_v7_0)
for i, x in enumerate(_io_v7_2): for i, x in enumerate(_io_v7_2):
if x[:2] == ("user_led_n", 0): if x[:2] == ("user_led_n", 0):
# TODO fix in HW _io_v7_2[i] = ("user_led_n", 0, Pins("L2"), IOStandard("LVCMOS33"))
#_io_v7_2[i] = ("user_led_n", 0, Pins("L2"), IOStandard("LVCMOS33"))
_io_v7_2[i] = ("user_led_n", 0, Pins("J19"), IOStandard("LVCMOS33"))
break break
# optional, alternative uart location # optional, alternative uart location

View File

@ -34,14 +34,23 @@ class CircularBuffer(Module):
rd_ptr = Signal(ptr_width) rd_ptr = Signal(ptr_width)
empty = Signal(reset=1) # Extra signal to distinguish between full and empty condition empty = Signal(reset=1) # Extra signal to distinguish between full and empty condition
# TODO this shouldn't be needed. Bug in migen IMO, I don't use this signal
dat_r = Signal(width)
# Hook write input signals to memory # Hook write input signals to memory
wr_port = storage.get_port(write_capable=True) wr_port = storage.get_port(write_capable=True)
# TODO hacky bullshit because migen is broken or I'm using it wrong
if not hasattr(wr_port.clock, "cd"):
wr_port.clock.cd = "sys"
# Always ready to write data into memory, so hook these signals straight in # Always ready to write data into memory, so hook these signals straight in
self.comb += [ self.comb += [
wr_port.adr.eq(wr_ptr), wr_port.adr.eq(wr_ptr),
wr_port.dat_w.eq(self.wr_data), wr_port.dat_w.eq(self.wr_data),
wr_port.we.eq(self.wr_valid), wr_port.we.eq(self.wr_valid),
self.wr_ready.eq(1), # We are always ready to write data in self.wr_ready.eq(1), # We are always ready to write data in
dat_r.eq(wr_port.dat_r)
] ]
# Advance write (and potentially read) # Advance write (and potentially read)
@ -66,6 +75,10 @@ class CircularBuffer(Module):
# TODO should I actually set async_read? # TODO should I actually set async_read?
rd_port = storage.get_port(async_read=True) rd_port = storage.get_port(async_read=True)
# TODO hacky bullshit because migen is broken or I'm using it wrong
if not hasattr(rd_port.clock, "cd"):
rd_port.clock.cd = "sys"
# Set read addr so 0 starts at rd_ptr and wraps around, and connect read data up # Set read addr so 0 starts at rd_ptr and wraps around, and connect read data up
self.comb += [ self.comb += [
If(self.rd_addr + rd_ptr < depth, If(self.rd_addr + rd_ptr < depth,

View File

@ -3,14 +3,9 @@ from migen.genlib.cdc import PulseSynchronizer
class Sampler(Module): class Sampler(Module):
def __init__(self, adc_pins: Record, sampler_clock: Signal): def __init__(self, adc_pins: Record):
# self.clock_domains.foo = ClockDomain() is how to add a new clock domain, accessible at self.foo
# Connect sampler clock domain
self.clock_domains.sample_clock = ClockDomain("sample_clock")
self.comb += self.sample_clock.clk.eq(sampler_clock)
# Hook up ADC REFCLK to sample_clock # Hook up ADC REFCLK to sample_clock
self.comb += adc_pins.refclk.eq(sampler_clock) self.comb += adc_pins.refclk.eq(ClockDomain("sample_clock").clk)
# We can synchronize to the sampler clock, whenever it goes high we can # We can synchronize to the sampler clock, whenever it goes high we can
# strobe a single valid signal # strobe a single valid signal
@ -21,10 +16,10 @@ class Sampler(Module):
self.data = Signal(10) self.data = Signal(10)
self.comb += [ self.comb += [
synchronizer.i.eq(self.sample_clock.clk), synchronizer.i.eq(ClockDomain("sample_clock").clk),
self.valid.eq(synchronizer.o), self.valid.eq(synchronizer.o),
self.data.eq(adc_pins.data),
] ]
self.sync += self.data.eq(adc_pins.data)
# Set config pins to constant values # Set config pins to constant values
self.comb += adc_pins.oen_b.eq(0) # Data pins enable self.comb += adc_pins.oen_b.eq(0) # Data pins enable