micropython control of SPI works (as far as I can tell)

This commit is contained in:
Peter McGoron 2024-03-12 10:01:46 +00:00
parent df9a7dcd8d
commit 3fac5747cc
6 changed files with 52 additions and 10 deletions

View File

@ -49,7 +49,12 @@ class Waveform(LiteXModule):
origin= 0x18,
bitwidth= 16,
rw= True,
)
),
"force_stop" : Register (
origin=0x1C,
bitwidth=1,
rw=True,
),
}
width = 0x20
@ -85,6 +90,7 @@ class Waveform(LiteXModule):
wform_size = Signal(counter_max_wid)
timer = Signal(timer_wid)
timer_spacing = Signal(timer_wid)
force_stop = Signal()
self.sync += If(b.cyc & b.stb & ~b.ack,
Case(b.adr, {
@ -118,6 +124,11 @@ class Waveform(LiteXModule):
).Else(
b.dat_r[0:timer_wid].eq(timer_spacing),
),
0x1C: If(b.we,
force_stop.eq(b.dat_w[0]),
).Else(
b.dat_r[0].eq(force_stop),
),
# (W)A(V)EFO(RM)
"default": b.dat_r.eq(0xAEF0AEF0),
}
@ -136,6 +147,7 @@ class Waveform(LiteXModule):
i_clk = ClockSignal(),
i_run = run,
i_force_stop = force_stop,
o_cntr = cntr,
i_do_loop = do_loop,
o_finished = finished,
@ -190,11 +202,11 @@ class SPIMaster(Module):
width = 0x20
public_registers = {
# The first bit is the "finished" bit, when the master is
# armed and finished with a transmission.
# The second bit is the "ready" bit, when the master is
# The first bit is the "ready" bit, when the master is
# not armed and ready to be armed.
"ready_or_finished": Register(
# The second bit is the "finished" bit, when the master is
# armed and finished with a transmission.
"finished_or_ready": Register(
origin= 0,
bitwidth= 2,
rw=False,
@ -224,7 +236,7 @@ class SPIMaster(Module):
# Same as ready_or_finished, but halts until ready or finished
# goes high. Dangerous, might cause cores to hang!
"wait_ready_or_finished": Register(
"wait_finished_or_ready": Register(
origin=0x10,
bitwidth=2,
rw= False,
@ -333,7 +345,8 @@ class SPIMaster(Module):
p_PHASE = phase,
i_clk = ClockSignal(),
i_rst_L = rst,
# module_reset is active high
i_rst_L = ~rst,
i_miso = miso,
o_mosi = mosi,
o_sck_wire = sck,

View File

@ -15,6 +15,7 @@ module waveform #(
/* Waveform output control */
input run,
input force_stop,
output reg[COUNTER_MAX_WID-1:0] cntr,
input do_loop,
output reg finished,
@ -57,7 +58,9 @@ localparam WAIT_PERIOD = 13;
reg [4-1:0] state = CHECK_START;
always @ (posedge clk) case (state)
always @ (posedge clk) if (force_stop) begin
state <= CHECK_START;
end else case (state)
CHECK_START: if (run) begin
cntr <= 0;
ready <= 0;

View File

@ -15,6 +15,7 @@ module waveform_sim #(
/* Waveform output control */
input run,
input force_stop,
output [COUNTER_MAX_WID-1:0] cntr,
input do_loop,
output finished,
@ -52,6 +53,7 @@ waveform #(
) wf (
.clk(clk),
.run(run),
.force_stop(force_stop),
.cntr(cntr),
.do_loop(do_loop),
.finished(finished),

View File

@ -274,7 +274,7 @@ class UpsilonSoC(SoCCore):
def f(csrs):
wid = kwargs["spi_wid"]
origin = csrs["memories"][name.lower() + "_pi"]['base']
return f'{name} = SPI({wid}, {origin}, {spi.mmio(origin)})'
return f'{name} = SPI({wid}, {name}_PI, {origin}, {spi.mmio(origin)})'
self.mmio_closures.append(f)
return spi, pi

View File

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

View File

@ -38,6 +38,10 @@ class Waveform(Immutable):
while self.regs.finished_or_ready == 0:
pass
def force_stop(self):
self.regs.force_stop = 1
selff.regs.force_stop = 0
def dump(self):
""" Dump contents of control registers. """
return self.regs.dump()