waveform sucessfully runs

This commit is contained in:
Peter McGoron 2024-03-14 10:02:47 +00:00
parent 3fac5747cc
commit 26fcd0af59
7 changed files with 47 additions and 26 deletions

View File

@ -93,41 +93,40 @@ class Waveform(LiteXModule):
force_stop = Signal() force_stop = Signal()
self.sync += If(b.cyc & b.stb & ~b.ack, self.sync += If(b.cyc & b.stb & ~b.ack,
Case(b.adr, { Case(b.adr[0:5], {
0x0: If(b.we, 0x0: If(b.we,
run.eq(b.dat_w[0]), run.eq(b.dat_w[0]),
).Else( ).Else(
b.dat_r[0].eq(run) b.dat_r.eq(run)
), ),
0x4: [ 0x4: [
b.dat_r[0:counter_max_wid].eq(cntr), b.dat_r.eq(cntr),
], ],
0x8: [ 0x8: [
If(b.we, If(b.we,
do_loop.eq(b.dat_w[0]), do_loop.eq(b.dat_w[0]),
).Else( ).Else(
b.dat_r[0].eq(do_loop), b.dat_r.eq(do_loop),
) )
], ],
0xC: [ 0xC: [
b.dat_r[0].eq(ready), b.dat_r.eq(finished << 1 | ready),
b.dat_r[1].eq(finished),
], ],
0x10: If(b.we, 0x10: If(b.we,
wform_size.eq(b.dat_w[0:counter_max_wid]), wform_size.eq(b.dat_w[0:counter_max_wid]),
).Else( ).Else(
b.dat_r[0:counter_max_wid].eq(wform_size) b.dat_r.eq(wform_size)
), ),
0x14: b.dat_r[0:timer_wid].eq(timer), 0x14: b.dat_r.eq(timer),
0x18: If(b.we, 0x18: If(b.we,
timer_spacing.eq(b.dat_w[0:timer_wid]), timer_spacing.eq(b.dat_w[0:timer_wid]),
).Else( ).Else(
b.dat_r[0:timer_wid].eq(timer_spacing), b.dat_r.eq(timer_spacing),
), ),
0x1C: If(b.we, 0x1C: If(b.we,
force_stop.eq(b.dat_w[0]), force_stop.eq(b.dat_w[0]),
).Else( ).Else(
b.dat_r[0].eq(force_stop), b.dat_r.eq(force_stop),
), ),
# (W)A(V)EFO(RM) # (W)A(V)EFO(RM)
"default": b.dat_r.eq(0xAEF0AEF0), "default": b.dat_r.eq(0xAEF0AEF0),

View File

@ -67,6 +67,7 @@ CHECK_START: if (run) begin
state <= CHECK_LEN; state <= CHECK_LEN;
end else begin end else begin
ready <= 1; ready <= 1;
finished <= 0;
end end
CHECK_LEN: if (cntr >= wform_size) begin CHECK_LEN: if (cntr >= wform_size) begin
if (do_loop) begin if (do_loop) begin
@ -79,11 +80,9 @@ CHECK_LEN: if (cntr >= wform_size) begin
state <= READ_RAM; state <= READ_RAM;
end end
WAIT_FINISHED: if (!run) begin WAIT_FINISHED: if (!run) begin
finished <= 0;
state <= CHECK_START; state <= CHECK_START;
end else if (do_loop) begin end else if (do_loop) begin
state <= READ_RAM; state <= READ_RAM;
finished <= 0;
cntr <= 0; cntr <= 0;
end else begin end else begin
finished <= 1; finished <= 1;
@ -174,7 +173,6 @@ end
* master switch for the DAC to the main CPU. * master switch for the DAC to the main CPU.
*/ */
WAIT_PERIOD: if (!run) begin WAIT_PERIOD: if (!run) begin
finished <= 0;
state <= CHECK_START; state <= CHECK_START;
end else if (timer < timer_spacing) begin end else if (timer < timer_spacing) begin
timer <= timer + 1; timer <= timer + 1;

View File

@ -305,6 +305,9 @@ class UpsilonSoC(SoCCore):
return self.add_spi_master(name, **args) return self.add_spi_master(name, **args)
def add_waveform(self, name, ram_len, **kwargs): def add_waveform(self, name, ram_len, **kwargs):
# TODO: Either set the SPI interface at instantiation time,
# or allow waveform to read more than one SPI bus (either by
# master switching or addressing by Waveform).
kwargs['counter_max_wid'] = minbits(ram_len) kwargs['counter_max_wid'] = minbits(ram_len)
wf = Waveform(**kwargs) wf = Waveform(**kwargs)
@ -316,8 +319,8 @@ class UpsilonSoC(SoCCore):
wf.add_ram(bram_pi.add_master(name), ram_len) wf.add_ram(bram_pi.add_master(name), ram_len)
def f(csrs): def f(csrs):
origin = csrs["memories"][name.lower() + "_pi"]["base"] param_origin = csrs["memories"][name.lower() + "_pi"]["base"]
return f'{name} = RegisterRegion({origin}, {wf.mmio(origin)})' return f'{name} = Waveform({name}_ram, {name}_PI, {name}_ram_PI, RegisterRegion({param_origin}, {wf.mmio(param_origin)}))'
self.mmio_closures.append(f) self.mmio_closures.append(f)
return wf, pi return wf, pi

View File

@ -2,7 +2,7 @@
.SUFFIXES: .mpy .py .SUFFIXES: .mpy .py
MPY=picorv32.mpy registers.mpy spi.mpy waveform.mpy mmio.mpy MPY=picorv32.mpy registers.mpy spi.mpy waveform.mpy mmio.mpy random.mpy
all: $(MPY) all: $(MPY)
.py.mpy: .py.mpy:

10
linux/random.py Normal file
View File

@ -0,0 +1,10 @@
class RandomGenerator:
# XorShift
def __init__(self, seed=2463534242):
self.seed = seed
def __call__(self):
self.seed = self.seed ^ ((self.seed << 13) & 0xFFFFFFFF)
self.seed = self.seed ^ ((self.seed >> 17) & 0xFFFFFFFF)
self.seed = self.seed ^ ((self.seed << 5) & 0xFFFFFFFF)
return self.seed

View File

@ -3,14 +3,14 @@ from registers import *
class SPI(RegisterRegion): class SPI(RegisterRegion):
def __init__(self, spiwid, spi_PI, origin, **regs): def __init__(self, spiwid, spi_PI, origin, **regs):
self.spiwid = spiwid self.spiwid = spiwid
self.spi_PI = spi_PI self.PI = spi_PI
super().__init__(origin, **regs) super().__init__(origin, **regs)
def send(self, val, force=False): def send(self, val, force=False):
if self.spi_PI.v != 0 and not force: if self.PI.v != 0 and not force:
raise Exception("SPI is controlled by another master") raise Exception("SPI is controlled by another master")
self.spi_PI.v = 0 self.PI.v = 0
self.arm.v = 0 self.arm.v = 0
while self.finished_or_ready.v == 0: while self.finished_or_ready.v == 0:

View File

@ -1,23 +1,34 @@
from registers import * from registers import *
class Waveform(Immutable): class Waveform(Immutable):
def __init__(self, ram, ram_pi, regs): def __init__(self, ram, wf_pi, ram_pi, regs):
super().__init__() super().__init__()
self.wf_pi = wf_pi
self.ram = ram self.ram = ram
self.ram_pi = ram_pi self.ram_pi = ram_pi
self.regs = regs self.regs = regs
self.make_immutable() self.make_immutable()
def run(self, wf, timer_spacing, do_loop = False): def start(self, wf, timer_spacing, do_loop = False, force_control=False):
""" Start waveform with signal. """ Start waveform with signal.
Note that a transfer of control of the SPI bus to the Waveform
must be done manually.
:param wf: Array of integers that describe the waveform. :param wf: Array of integers that describe the waveform.
These are twos-complement 20-bit integers. These are twos-complement 20-bit integers.
:param timer_spacing: The amount of time to wait between :param timer_spacing: The amount of time to wait between
points on the waveform. points on the waveform.
:param do_loop: If True, the waveform will repeat. :param do_loop: If True, the waveform will repeat.
:param force_control: If True, will take control of the Waveform
even if it is being controlled by another Wishbone bus.
""" """
if self.wf_pi.v != 0:
if not force_control:
raise Exception("Waveform is not controlled by master")
self.wf_pi.v = 0
self.stop() self.stop()
self.ram_pi.v = 0 self.ram_pi.v = 0
@ -32,15 +43,15 @@ class Waveform(Immutable):
def stop(self): def stop(self):
""" Stop the waveform and wait until it is ready. """ """ Stop the waveform and wait until it is ready. """
self.regs.run = 0 self.regs.run.v = 0
self.regs.do_loop = 0 self.regs.do_loop.v = 0
while self.regs.finished_or_ready == 0: while self.regs.finished_or_ready.v == 0:
pass pass
def force_stop(self): def force_stop(self):
self.regs.force_stop = 1 self.regs.force_stop.v = 1
selff.regs.force_stop = 0 selff.regs.force_stop.v = 0
def dump(self): def dump(self):
""" Dump contents of control registers. """ """ Dump contents of control registers. """