class DFF_TB(object): def __init__(self, dut, init_val): """ Setup the testbench. *init_val* signifies the ``BinaryValue`` which must be captured by the output monitor with the first rising clock edge. This must match the initial state of the D flip-flop in RTL. """ # Some internal state self.dut = dut self.stopped = False # Create input driver and output monitor self.input_drv = BitDriver(signal=dut.d, clk=dut.c, generator=input_gen()) self.output_mon = BitMonitor(name="output", signal=dut.q, clk=dut.c) # Create a scoreboard on the outputs self.expected_output = [init_val ] # a list with init_val as the first element with warnings.catch_warnings(): warnings.simplefilter("ignore") self.scoreboard = Scoreboard(dut) self.scoreboard.add_interface(self.output_mon, self.expected_output) # Use the input monitor to reconstruct the transactions from the pins # and send them to our 'model' of the design. self.input_mon = BitMonitor(name="input", signal=dut.d, clk=dut.c, callback=self.model) def model(self, transaction): """Model the DUT based on the input *transaction*. For a D flip-flop, what goes in at ``d`` comes out on ``q``, so the value on ``d`` (put into *transaction* by our ``input_mon``) can be used as expected output without change. Thus we can directly append *transaction* to the ``expected_output`` list, except for the very last clock cycle of the simulation (that is, after ``stop()`` has been called). """ if not self.stopped: self.expected_output.append(transaction) def start(self): """Start generating input data.""" self.input_drv.start() def stop(self): """Stop generating input data. Also stop generation of expected output transactions. One more clock cycle must be executed afterwards so that the output of the D flip-flop can be checked. """ self.input_drv.stop() self.stopped = True
class TB(object): def __init__(self, dut): # Some internal state self.dut = dut self.stopped = False # Use the input monitor to reconstruct the transactions from the pins # and send them to our 'model' of the design. self.input_mon = BitMonitor(name="input", signal=dut.Zybo_Example_sw_in, clk=dut.clk, callback=self.model) # Create input driver and output monitor self.input_drv = BitDriver(signal=dut.Zybo_Example_sw_in, clk=dut.clk, generator=input_gen()) self.output_mon = BitMonitor(name="output", signal=dut.Zybo_Example_leds_out, clk=dut.clk) # Create a scoreboard on the outputs self.expected_output = [] self.scoreboard = Scoreboard(dut) self.scoreboard.add_interface(self.output_mon, self.expected_output) def model(self, transaction): if not self.stopped: self.expected_output.append(transaction) def start(self): self.input_drv.start() def stop(self): self.input_drv.stop() self.stopped = True
class DFF_TB(object): def __init__(self, dut, init_val): """ Setup testbench. init_val signifies the BinaryValue which must be captured by the output monitor with the first risign edge. This is actually the initial state of the flip-flop. """ # Some internal state self.dut = dut self.stopped = False # Create input driver and output monitor self.input_drv = BitDriver(dut.d, dut.c, input_gen()) self.output_mon = BitMonitor("output", dut.q, dut.c) # Create a scoreboard on the outputs self.expected_output = [ init_val ] self.scoreboard = Scoreboard(dut) self.scoreboard.add_interface(self.output_mon, self.expected_output) # Reconstruct the input transactions from the pins # and send them to our 'model' self.input_mon = BitMonitor("input", dut.d, dut.c, callback=self.model) def model(self, transaction): """Model the DUT based on the input transaction.""" # Do not append an output transaction for the last clock cycle of the # simulation, that is, after stop() has been called. if not self.stopped: self.expected_output.append(transaction) def start(self): """Start generation of input data.""" self.input_drv.start() def stop(self): """ Stop generation of input data. Also stop generation of expected output transactions. One more clock cycle must be executed afterwards, so that, output of D-FF can be checked. """ self.input_drv.stop() self.stopped = True
class ImpulseGeneratorTB(object): def __init__(self, dut): """ Setup testbench. """ # Some internal state self.dut = dut self.stopped = False # Create input driver and output monitor self.input_drv = BitDriver(dut.enable, dut.clk, input_gen()) dut.enable <= 0 self.output_mon = BitMonitor("output", dut.impulse, dut.clk) # Create a scoreboard on the outputs self.expected_output = [BinaryValue(0, 1)] self.scoreboard = Scoreboard(dut) self.scoreboard.add_interface(self.output_mon, self.expected_output) # Reconstruct the input transactions from the pins # and send them to our 'model' self.input_mon = BitMonitor("input", dut.enable, dut.clk, callback=self.model) # Model variables self.triggered = False self.counter = 0 @cocotb.coroutine def reset(self, duration=100000): self.dut._log.debug("Resetting DUT") self.dut.rst <= 1 yield Timer(duration) yield RisingEdge(self.dut.clk) self.dut.rst <= 0 self.dut._log.debug("Out of reset") def model(self, transaction): """ Model the DUT based on the input transaction. """ # Do not append an output transaction for the last clock cycle of the # simulation, that is, after stop() has been called. if not self.stopped: print "--- PING" print(type(transaction)) print(transaction.integer) if self.triggered: print "Appending 1" self.expected_output.append(BinaryValue(1, 1)) self.counter = self.counter + 1 if self.counter == 21 - 1: self.triggered = False else: print "Appending 0" if transaction.integer == 0: self.expected_output.append(BinaryValue(0, 1)) if transaction.integer == 1: self.expected_output.append(BinaryValue(1, 1)) self.counter = self.counter = 0 self.triggered = True # self.expected_output.append(transaction) def start(self): """Start generation of input data.""" self.input_drv.start() def stop(self): """ Stop generation of input data. Also stop generation of expected output transactions. """ self.input_drv.stop() self.stopped = True