def test_ffe(dut): cocotb.fork(Clock(dut.clk, 1, units='ns').start()) yield reset(dut) dut.en <= 1 yield Timer(10, units='ns') fir_output = np.zeros(100, dtype=int) fir_input_prbs = np.random.choice([128, 1920], (100)) fir_input_pulse = np.concatenate((np.ones(50) * 128, np.ones(50) * -128)) for i, val in enumerate(fir_input_prbs.astype('int')): dut.din <= val yield RisingEdge(dut.clk) fir_output[i] = dut.dout.value.signed_integer # test read_values yield Timer(10, units='ns') plt.figure() plt.plot(np.where(fir_input_prbs == 128, 128, -128)) plt.plot(fir_output) plt.show(block=True) #_ = input('Presione enter para terminar') plt.close()
def test_counter(dut): cocotb.fork(Clock(dut.clockdsp, 1, units='ns').start()) yield reset(dut) dut.log_in_ram_run_from_micro <= 1 yield RisingEdge(dut.log_out_full_from_ram) dut.log_in_ram_run_from_micro <= 0 yield Timer(10, units='ns') read_values = [] for address in range(2**15): dut.log_read_addr_from_micro <= address yield RisingEdge(dut.clockdsp) read_values.append(dut.log_read_addr_from_micro.value.integer) # test read_values yield Timer(10, units='ns') values = list(range(2**15)) if values != read_values: print(read_values) raise TestFailure("Los valores no coinciden")
def async_rst(self): """ This function execute the reset_n for 40ns it also set all input signals to default value """ self.dut._log.info("begin Rst") for n, t in self.dut._sub_handles.items(): if isinstance(t, handle.ModifiableObject): t.value = 0 yield Timer(40, 'ns') self.dut.reset_n <= 1 yield Timer(15, 'ns') self.dut._log.info("end Rst")
def test_cordic(dut): cocotb.fork(Clock(dut.clk, 1, units='ns').start()) yield reset(dut) for i in range(16): dut.en_i <= 1 dut.data <= i yield Timer(12, units='ns') dut.en_i <= 0 yield Timer(1, units='ns') yield RisingEdge(dut.clk) for _ in range(10): yield RisingEdge(dut.clk)
def test_cordic(dut): cocotb.fork(Clock(dut.clk, 1, units='ns').start()) yield reset(dut) # yield Timer(12, units='ns') for i in range(len(xValues)): dut.en_i <= 1 dut.x_i <= xValues[i] dut.y_i <= yValues[i] yield Timer(1, units='ns') dut.en_i <= 0 yield Timer(13, units='ns') yield RisingEdge(dut.clk) for _ in range(10): yield RisingEdge(dut.clk)
def reset(dut): dut.run <= 0 dut.rst <= 1 yield Timer(15, units='ns') yield RisingEdge(dut.clk) dut.rst <= 0 yield RisingEdge(dut.clk) dut.rst._log.info("Reset complete")
def reset(dut): dut.start <= 0 dut.din <= 0 dut.rst <= 1 yield Timer(1500) yield RisingEdge(dut.clk) dut.rst <= 0 yield RisingEdge(dut.clk) dut.rst._log.info("Reset complete")
def test_cordic(dut): cocotb.fork(Clock(dut.clk, 1, units='ns').start()) yield reset(dut) dut.en_i <= 1 yield Timer(99, units='ns') yield RisingEdge(dut.clk) dut.en_i <= 0 dut.rst <= 1 for _ in range(10): yield RisingEdge(dut.clk)
def test_counter(dut): cocotb.fork(Clock(dut.clk, 1, units='ns').start()) yield reset(dut) dut.run <= 1 yield Timer(99, units='ns') yield RisingEdge(dut.clk) dut.run <= 0 for _ in range(10): yield RisingEdge(dut.clk)
def reset(dut): dut.en_i <= 0 dut.rst <= 1 dut.x_i <= 0 dut.y_i <= 1000 dut.z_i <= 0 yield Timer(15, units='ns') yield RisingEdge(dut.clk) dut.rst <= 0 yield RisingEdge(dut.clk) dut.rst._log.info("Reset complete")
def reset(dut): dut.soft_reset <= 1 dut.step_mu <= 0 dut.connect_ch_to_dsp <= 0 dut.rf_enables_module <= 0 dut.log_in_ram_run_from_micro <= 0 dut.log_read_addr_from_micro <= 0 yield Timer(15, units='ns') yield RisingEdge(dut.clockdsp) dut.soft_reset <= 0 yield RisingEdge(dut.clockdsp) dut.soft_reset._log.info("Reset complete")
def reset(dut): dut.rst <= 1 dut.en <= 0 dut.din <= 0 dut.coef0 <= 0 dut.coef1 <= 0 dut.coef2 <= 0 dut.coef3 <= 128 dut.coef4 <= 0 dut.coef5 <= 0 dut.coef6 <= 0 yield Timer(15, units='ns') yield RisingEdge(dut.clk) dut.rst <= 0 yield RisingEdge(dut.clk) dut.rst._log.info("Reset complete")
def test_dsp(dut): cocotb.fork(Clock(dut.clockdsp, 1, units='ns').start()) yield reset(dut) yield Timer(10, units='ns') dut.step_mu <= 4 # 0,1,4,16 N = 1000 dut.rf_enables_module <= 1 fir_output = np.zeros(N, dtype=int) err_output = np.zeros(N, dtype=int) coefs_out = np.zeros((N, 7), dtype=int) fir_input_prbs = np.convolve(np.random.choice([128, -128], (N)), channel[ch_sel], mode='same') fir_input_pulse = np.concatenate((np.ones(50) * 128, np.ones(50) * -128)) for i, val in enumerate(fir_input_prbs.astype('int')): dut.connect_ch_to_dsp <= val yield RisingEdge(dut.clockdsp) fir_output[i] = dut.ffe_inst.o_data.value.signed_integer err_output[i] = dut.error.value.signed_integer for k in range(7): coefs_out[i, k] = dut.ffe_inst.coefs[k].value.signed_integer # test read_values yield Timer(10, units='ns') plt.figure() plt.plot(np.where(fir_input_prbs == 128, 128, -128)) plt.plot(fir_output) plt.figure() plt.plot(err_output) plt.figure() plt.subplot(2, 1, 1) plt.stem(fir_output[0:200]) plt.grid() plt.ylim((np.min(fir_output) - 0.5, np.max(fir_output) + 0.5)) plt.ylabel('Amplitude') plt.xlabel('Samples') plt.title('FFE Output and Error - HW') plt.subplot(2, 1, 2) plt.plot(err_output) plt.grid() plt.ylim((np.min(err_output) - 0.5, np.max(err_output) + 0.5)) plt.ylabel('Amplitude') plt.xlabel('Samples') plt.figure() plt.subplot(3, 1, 1) plt.plot(coefs_out) plt.grid() plt.ylim((min(coefs_out[len(coefs_out) - 1]) - 12, max(coefs_out[len(coefs_out) - 1]) + 12)) plt.ylabel('Amplitude') plt.title('Taps of FFE') plt.subplot(3, 1, 2) plt.stem(coefs_out[len(coefs_out) - 1]) plt.grid() plt.ylim((min(coefs_out[len(coefs_out) - 1]) - 0.5, max(coefs_out[len(coefs_out) - 1]) + 0.5)) plt.ylabel('Amplitude') plt.subplot(3, 1, 3) plt.stem(np.convolve(channel[ch_sel], coefs_out[len(coefs_out) - 1])) plt.grid() plt.ylim((min(coefs_out[len(coefs_out) - 1]) - 0.5, max(coefs_out[len(coefs_out) - 1]) + 0.5)) plt.ylabel('Conv.Ch.Taps') plt.xlabel('Samples') plt.show(block=True) plt.close()
def test_tree(dut): """Testing APBI2C core""" log = cocotb.logging.getLogger("cocotb.test") cocotb.fork(Clock(dut.PCLK, 1000).start()) #instantiate the APB agent (monitor and driver) (see apb.py) apb = APBSlave(dut, name=None, clock=dut.PCLK) #instantiate the I2C monitor and driver (see i2c.py) i2c_monitor = I2CMonitor(dut, name="", clock=dut.PCLK) i2c_driver = I2CDriver(dut, name=None, clock=dut.PCLK) #write to config register via APB @cocotb.coroutine def config_write(addr, data): xaction = APBTransaction(addr, data, write=True) xaction.randomize() yield apb.send(xaction) #store observed I2C transactions received_i2c_xactions = [] #the catcher for observerd I2C transaction on the interfece @I2CCoverage def i2c_xaction_catcher(i2c_xaction): if LOG_XACTION_ENABLE: log.info("I2C Monitor: Transaction 0x%08X" % i2c_xaction.data) received_i2c_xactions.append(i2c_xaction) #callback to the monitor to call the catcher when I2C transaction observed i2c_monitor.add_callback(i2c_xaction_catcher) #the catcher for observerd APB transaction on the interfece @APBCoverage def apb_xaction_catcher(apb_xaction): if LOG_XACTION_ENABLE: try: log.info("APB Transaction %s 0x%08X -> 0x%08X" % ("Write" if apb_xaction.write else "Read ", int(apb_xaction.addr), int(apb_xaction.data))) except: log.info("APB Transaction %s 0x%08X -> 0x%08s" % ("Write" if apb_xaction.write else "Read ", int(apb_xaction.addr), int(apb_xaction.data))) #callback to the monitor to call the catcher when APB transaction observed apb.add_callback(apb_xaction_catcher) #define "I2C Operation" as a bunch of r/ws with defined number of data #and a specific clock divider #this is the main stuff to be tested - we want to know if controller #correctly processes transfers with different directions, amount of #data and SCK period class I2C_Operation(Randomized): def __init__(self, direction='write', repeat=1, divider=1): Randomized.__init__(self) self.direction = direction self.repeat = repeat self.divider = divider self.repeat_range = (1, 3) self.divider_range = (1, 3) #I2C_Operation objects may be fully randomized self.addRand("direction", ["write", "read"]) self.addRand("repeat_range", [(1, 3), (4, 7), (8, 11), (12, 15), (16, 23), (24, 31)]) self.addRand("divider_range", [(1, 3), (4, 7), (8, 11), (12, 15), (16, 23), (24, 31)]) #post_randomize to pick random values from already randomized ranges def post_randomize(self): self.repeat = random.randint(self.repeat_range[0], self.repeat_range[1]) self.divider = random.randint(self.divider_range[0], self.divider_range[1]) #list of completed operations for the summary operations_completed = [] #function sampling operations order coverage (see coverage.py) @OperationsOrderCoverage def sample_operations_order_coverage(prev_operation, operation): pass #function sampling operations coverage (see coverage.py) @OperationsCoverage def sample_operation(operation, ok): operations_completed.append((operation, ok)) if (len(operations_completed) > 1): sample_operations_order_coverage(operations_completed[-2][0], operations_completed[-1][0]) if ok: log.info( "Operation %s of %d words, divider %d - OK!" % (operation.direction, operation.repeat, operation.divider)) else: log.error( "Operation %s of %d words, divider %d - error!" % (operation.direction, operation.repeat, operation.divider)) #a test sequence - complete I2C Write Operation @cocotb.coroutine def segment_i2c_write_operation(operation): expected_out = [] yield config_write(8, 0x0001 | (operation.divider << 2)) #create xaction objects and fill FIFO up via APB with data to be send apb_xaction = APBTransaction(0, 0, write=True) for i in range(operation.repeat): i2c_xaction = I2CTransaction(0, write=False) i2c_xaction.randomize() apb_xaction.data = i2c_xaction.data apb_xaction.randomize() yield apb.send(apb_xaction) expected_out.append(i2c_xaction) #wait for FIFO empty - meaning all data sent out guard_int = 0 while not dut.INT_TX.value: guard_int = guard_int + 1 yield RisingEdge(dut.PCLK) if guard_int == 50000: raise TestFailure("Controller hang-up!") #a simple scoreboarding... #compare data written to APB with catched on I2C interface ok = True received_xactions = received_i2c_xactions[-operation.repeat:] if len(received_xactions) < operation.repeat: ok = False else: for i in range(operation.repeat): if (received_xactions[i] != expected_out[i]): ok = False break #call sampling at the and of the sequence sample_operation(operation, ok) #a test sequence - complete I2C Read Operation @cocotb.coroutine def segment_i2c_read_operation(operation): expected_in = [] yield config_write(8, 0x0002 | (operation.divider << 2)) #create I2C xaction objects and send on the interface for i in range(operation.repeat): i2c_xaction = I2CTransaction(0, write=True) i2c_xaction.randomize() expected_in.append(i2c_xaction) yield i2c_driver.send(i2c_xaction) #a simple scoreboarding... #compare data written on I2C interface with read from FIFO ok = True apb_xaction = APBTransaction(0x04, 0, write=False) for i in range(operation.repeat): try: apb_xaction.randomize() rdata = yield apb.send(xaction) if (rdata != expected_in[i].data): ok = False except: if LOG_XACTION_ENABLE: log.error("APB read data from FIFO is 'X'") ok = False #call sampling at the and of the sequence sample_operation(operation, ok) #a test sequence - APB registers operation (sort of UVM_REG :) ) @cocotb.coroutine def segment_apb_rw(repeat=1, addr=0xC): apb_xaction_wr = APBTransaction(addr, 0, write=True) apb_xaction_rd = APBTransaction(addr, 0, write=False) #just do some APB/RW for i in range(repeat): data = random.randint(0, 0xFFFFFFFF) apb_xaction_wr.randomize() apb_xaction_wr.data = data yield apb.send(apb_xaction_wr) apb_xaction_rd.randomize() rdata = yield apb.send(apb_xaction_rd) if LOG_XACTION_ENABLE: try: if rdata != data: log.error( "APB read data @ 0x%08X does not match written value" % addr) except: log.error("APB read data @ 0x%08X is 'X'" % addr) #reset the DUT dut.PRESETn <= 0 yield Timer(2000) dut.PRESETn <= 1 yield config_write(12, 0x0100) #if checkpoints used, store them in the map, (see checkpoint.py) if ENABLE_CHECKPOINTS: checkpoints = {} get_checkpoint_hier(dut) #the fist checkpoint is just after reset checkpoints['init'] = (checkpoint(), None) #list of already covered operations, used to constraint the randomization already_covered = [] #constraint for the operation randomization - do not use already #covered combinations def op_constraint(direction, divider_range, repeat_range): return not (direction, repeat_range, divider_range) in already_covered apb_cover_item = coverage_db["top.apb.writeXdelay"] top_cover_item = coverage_db["top"] #we define test end condition as reaching 99% coverage at the #top cover item cov_op = 0 while cov_op < 90: #restore randomly selected checkpoint if ENABLE_CHECKPOINTS: if CHECKPOINTS_TREE_STRUCTURE: chkp_to_restore = random.choice(list(checkpoints.keys())) else: chkp_to_restore = 'init' log.info("Restoring a simulation checkpoint: " + chkp_to_restore) current_chceckpoint = checkpoints[chkp_to_restore] restore(current_chceckpoint[0]) #create I2C operation object to be executed i2c_op = I2C_Operation() #if there is no tree structure, knowledge about already covered #cases cannot be used if ENABLE_CHECKPOINTS & CHECKPOINTS_TREE_STRUCTURE: try: i2c_op.randomize_with(op_constraint) except: i2c_op.randomize() else: i2c_op.randomize() already_covered.append( (i2c_op.direction, i2c_op.repeat_range, i2c_op.divider_range)) #call test sequence if i2c_op.direction == "read": yield segment_i2c_read_operation(i2c_op) else: yield segment_i2c_write_operation(i2c_op) if ENABLE_CHECKPOINTS: #if status is OK, add this simulation point to the checkpoints list if operations_completed[-1][1]: chkp_name = str(get_sim_time('ns')) log.info("Creating a simulation checkpoint: " + chkp_name) checkpoints[chkp_name] = (checkpoint(), i2c_op) #call APB test sequence as long as cover item apb.writeXdelay #coverage level is below 100% if apb_cover_item.coverage * 100 / apb_cover_item.size < 100: yield segment_apb_rw(repeat=random.randint(1, 5)) #update the coverage level cov_op_prev = cov_op cov_op = top_cover_item.coverage * 100.0 / top_cover_item.size log.info("Current overall coverage level = %f %%", cov_op) #print summary log.info("Opertions finished succesfully:") for elem in operations_completed: if elem[1]: log.info(" %s of %d words with divider %d" % (elem[0].direction, elem[0].repeat, elem[0].divider)) log.info("Opertions finished with error:") for elem in operations_completed: if not elem[1]: log.info(" %s of %d words with divider %d" % (elem[0].direction, elem[0].repeat, elem[0].divider)) log.info("Functional coverage details:") reportCoverage(log.info, bins=False)