20e91e4e877948f72000b5ac789b053f82d21f4d
1 from nmigen
import Signal
, Cat
, Const
, Mux
, Module
2 from nmigen
.compat
.sim
import run_simulation
3 from nmigen
.cli
import verilog
, rtlil
8 self
.i_p_stb
= Signal() # >>in - comes in from PREVIOUS stage
9 self
.i_n_busy
= Signal() # in<< - comes in from the NEXT stage
10 self
.i_data
= Signal(32) # >>in - comes in from the PREVIOUS stage
11 #self.i_rst = Signal()
14 self
.r_data
= Signal(32)
17 self
.o_n_stb
= Signal() # out>> - goes out to the NEXT stage
18 self
.o_p_busy
= Signal() # <<out - goes out to the PREVIOUS stage
19 self
.o_data
= Signal(32) # out>> - goes out to the NEXT stage
21 def pre_process(self
, d_in
):
24 def process(self
, d_in
):
27 def elaborate(self
, platform
):
30 i_p_stb_o_p_busyn
= Signal(reset_less
=True)
31 m
.d
.comb
+= i_p_stb_o_p_busyn
.eq(self
.i_p_stb
& (~self
.o_p_busy
))
33 with m
.If(~self
.i_n_busy
): # previous stage is not busy
34 with m
.If(~self
.o_p_busy
): # not stalled
35 # nothing in buffer: send input direct to output
36 m
.d
.sync
+= self
.o_n_stb
.eq(self
.i_p_stb
)
37 m
.d
.sync
+= self
.o_data
.eq(self
.process(self
.i_data
))
38 with m
.Else(): # o_p_busy is true, and something is in our buffer.
39 # Flush the buffer to the output port.
40 m
.d
.sync
+= self
.o_n_stb
.eq(1)
41 m
.d
.sync
+= self
.o_data
.eq(self
.r_data
)
42 # ignore input, since o_p_busy is also true.
43 # also clear stall condition, declare register to be empty.
44 m
.d
.sync
+= self
.o_p_busy
.eq(0)
46 # (i_n_busy) is true here: previous stage is busy
47 with m
.Elif(~self
.o_n_stb
): # next stage being told "not busy"
48 m
.d
.sync
+= self
.o_n_stb
.eq(self
.i_p_stb
)
49 m
.d
.sync
+= self
.o_p_busy
.eq(0) # Keep the buffer empty
50 # Apply the logic to the input data, and set the output data
51 m
.d
.sync
+= self
.o_data
.eq(self
.process(self
.i_data
))
53 # (i_n_busy) and (o_n_stb) both true:
54 with m
.Elif(i_p_stb_o_p_busyn
):
55 # If next stage *is* busy, and not stalled yet, accept requested
56 # input and store in temporary
57 m
.d
.sync
+= self
.o_p_busy
.eq(self
.i_p_stb
& self
.o_n_stb
)
58 with m
.If(~self
.o_n_stb
):
59 m
.d
.sync
+= self
.r_data
.eq(self
.i_data
)
61 with m
.If(~self
.o_p_busy
): # not stalled
62 m
.d
.sync
+= self
.r_data
.eq(self
.pre_process(self
.i_data
))
67 return [self
.i_p_stb
, self
.i_n_busy
, self
.i_data
,
69 self
.o_n_stb
, self
.o_p_busy
, self
.o_data
74 yield dut
.i_data
.eq(5)
75 yield dut
.i_p_stb
.eq(1)
77 yield dut
.i_data
.eq(7)
79 yield dut
.i_data
.eq(2)
81 yield dut
.i_n_busy
.eq(1)
82 yield dut
.i_data
.eq(9)
84 yield dut
.i_data
.eq(12)
86 yield dut
.i_n_busy
.eq(0)
92 if __name__
== '__main__':
94 vl
= rtlil
.convert(dut
, ports
=dut
.ports())
95 with
open("test_bufpipe.il", "w") as f
:
97 run_simulation(dut
, testbench(dut
), vcd_name
="test_bufpipe.vcd")