From e1336d2ad072dc6661c9af1b0460a69ff1bf588f Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Tue, 12 Mar 2019 13:13:33 +0000 Subject: [PATCH] add example buffered pipe --- src/add/example_buf_pipe.py | 98 +++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 src/add/example_buf_pipe.py diff --git a/src/add/example_buf_pipe.py b/src/add/example_buf_pipe.py new file mode 100644 index 00000000..20e91e4e --- /dev/null +++ b/src/add/example_buf_pipe.py @@ -0,0 +1,98 @@ +from nmigen import Signal, Cat, Const, Mux, Module +from nmigen.compat.sim import run_simulation +from nmigen.cli import verilog, rtlil + +class BufPipe: + def __init__(self): + # input + self.i_p_stb = Signal() # >>in - comes in from PREVIOUS stage + self.i_n_busy = Signal() # in<< - comes in from the NEXT stage + self.i_data = Signal(32) # >>in - comes in from the PREVIOUS stage + #self.i_rst = Signal() + + # buffered + self.r_data = Signal(32) + + # output + self.o_n_stb = Signal() # out>> - goes out to the NEXT stage + self.o_p_busy = Signal() # <> - goes out to the NEXT stage + + def pre_process(self, d_in): + return d_in + + def process(self, d_in): + return d_in + 1 + + def elaborate(self, platform): + m = Module() + + i_p_stb_o_p_busyn = Signal(reset_less=True) + m.d.comb += i_p_stb_o_p_busyn.eq(self.i_p_stb & (~self.o_p_busy)) + + with m.If(~self.i_n_busy): # previous stage is not busy + with m.If(~self.o_p_busy): # not stalled + # nothing in buffer: send input direct to output + m.d.sync += self.o_n_stb.eq(self.i_p_stb) + m.d.sync += self.o_data.eq(self.process(self.i_data)) + with m.Else(): # o_p_busy is true, and something is in our buffer. + # Flush the buffer to the output port. + m.d.sync += self.o_n_stb.eq(1) + m.d.sync += self.o_data.eq(self.r_data) + # ignore input, since o_p_busy is also true. + # also clear stall condition, declare register to be empty. + m.d.sync += self.o_p_busy.eq(0) + + # (i_n_busy) is true here: previous stage is busy + with m.Elif(~self.o_n_stb): # next stage being told "not busy" + m.d.sync += self.o_n_stb.eq(self.i_p_stb) + m.d.sync += self.o_p_busy.eq(0) # Keep the buffer empty + # Apply the logic to the input data, and set the output data + m.d.sync += self.o_data.eq(self.process(self.i_data)) + + # (i_n_busy) and (o_n_stb) both true: + with m.Elif(i_p_stb_o_p_busyn): + # If next stage *is* busy, and not stalled yet, accept requested + # input and store in temporary + m.d.sync += self.o_p_busy.eq(self.i_p_stb & self.o_n_stb) + with m.If(~self.o_n_stb): + m.d.sync += self.r_data.eq(self.i_data) + + with m.If(~self.o_p_busy): # not stalled + m.d.sync += self.r_data.eq(self.pre_process(self.i_data)) + + return m + + def ports(self): + return [self.i_p_stb, self.i_n_busy, self.i_data, + self.r_data, + self.o_n_stb, self.o_p_busy, self.o_data + ] + + +def testbench(dut): + yield dut.i_data.eq(5) + yield dut.i_p_stb.eq(1) + yield + yield dut.i_data.eq(7) + yield + yield dut.i_data.eq(2) + yield + yield dut.i_n_busy.eq(1) + yield dut.i_data.eq(9) + yield + yield dut.i_data.eq(12) + yield + yield dut.i_n_busy.eq(0) + yield + yield + yield + + +if __name__ == '__main__': + dut = BufPipe() + vl = rtlil.convert(dut, ports=dut.ports()) + with open("test_bufpipe.il", "w") as f: + f.write(vl) + run_simulation(dut, testbench(dut), vcd_name="test_bufpipe.vcd") + -- 2.30.2