diff --git a/gateware/extio.py b/gateware/extio.py index 15c1e8c..b07475a 100644 --- a/gateware/extio.py +++ b/gateware/extio.py @@ -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, diff --git a/gateware/rtl/waveform/waveform.v b/gateware/rtl/waveform/waveform.v index f26524d..26a1149 100644 --- a/gateware/rtl/waveform/waveform.v +++ b/gateware/rtl/waveform/waveform.v @@ -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; diff --git a/gateware/rtl/waveform/waveform_sim.v b/gateware/rtl/waveform/waveform_sim.v index e8480b0..2982d41 100644 --- a/gateware/rtl/waveform/waveform_sim.v +++ b/gateware/rtl/waveform/waveform_sim.v @@ -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), diff --git a/gateware/soc.py b/gateware/soc.py index 3bb628c..922e86a 100644 --- a/gateware/soc.py +++ b/gateware/soc.py @@ -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 diff --git a/linux/spi.py b/linux/spi.py index 0c5884f..0bac286 100644 --- a/linux/spi.py +++ b/linux/spi.py @@ -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 diff --git a/linux/waveform.py b/linux/waveform.py index d9c8f00..12ff653 100644 --- a/linux/waveform.py +++ b/linux/waveform.py @@ -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()