import cocotb
from cocotb.triggers import Timer, RisingEdge, ClockCycles
from cocotb.clock import Clock
import cocotb_coverage
import random
import fractional_n_divider_model
from test_fractional_n_divider_coverage import *


# hardware constants
WIDTH_INTEGER = 10
WIDTH_MODULUS = 16
ORDER = 3


# test constants
NUMBER_TESTS = 64
NUMBER_SAMPLES = 2**16


@cocotb.test()
async def coverage(dut):
    """
        Test the output against the model with random input values
    """

    # create the model
    model = fractional_n_divider_model.fractional_n_divider_model(integer_width=WIDTH_INTEGER, modulus_width=WIDTH_MODULUS, order=ORDER)

    # create an object that views the DUT state
    status = FractionalNStatus(dut)

    # start clock
    clock = Clock(dut.input_frequency, 2)
    cocotb.fork(clock.start())    

    # loop through the tests
    for test in range(NUMBER_TESTS):

        # reset the DUT
        dut.rst = 1
        dut.divide_value = 0
        await ClockCycles(dut.input_frequency, 8)
        dut.rst = 0
        model.reset()

        # create some random data
        divide_value = random.random() * (2**WIDTH_INTEGER - 0.5*2**ORDER - 1)
        divide_value_fp = int(divide_value * 2**WIDTH_MODULUS)
        dut._log.info("Test number %d, input value = %f" % (test+1, divide_value))

        # change the divide value
        model.set_divide_value(divide_value)

        # update the divider value into the DUT
        status.update()
        output_data = await new_divider_value(dut, status, divide_value_fp)
        await RisingEdge(dut.input_frequency)

        # loop through some clock cycles calculating samples
        for sample in range(NUMBER_SAMPLES):

            # check the output matches the model
            model_data = model.update()
            output_data = int(dut.output_frequency)
            assert(output_data == model_data), 'Model = %x, Simulation = %x' % (model_data, output_data)

            await RisingEdge(dut.input_frequency)


    # print and export coverage report
    coverage_db.report_coverage(dut._log.info, bins=True)
    coverage_db.export_to_xml(filename="coverage_fractional_n_divider.xml")
    coverage_db.export_to_yaml(filename="coverage_fractional_n_divider.yml")
import cocotb
from cocotb.triggers import Timer, RisingEdge, ClockCycles
from cocotb.clock import Clock
import cocotb_coverage
import random
import fractional_n_divider_model
from test_fractional_n_divider_coverage import *


# hardware constants
WIDTH_INTEGER = 10
WIDTH_MODULUS = 16
ORDER = 3


# test constants
NUMBER_TESTS = 64
NUMBER_SAMPLES = 2**16


@cocotb.test()
async def coverage(dut):
    """
        Test the output against the model with random input values
    """

    # create the model
    model = fractional_n_divider_model.fractional_n_divider_model(integer_width=WIDTH_INTEGER, modulus_width=WIDTH_MODULUS, order=ORDER)

    # create an object that views the DUT state
    status = FractionalNStatus(dut)

    # start clock
    clock = Clock(dut.input_frequency, 2)
    cocotb.fork(clock.start())    

    # loop through the tests
    for test in range(NUMBER_TESTS):

        # reset the DUT
        dut.rst = 1
        dut.divide_value = 0
        await ClockCycles(dut.input_frequency, 8)
        dut.rst = 0
        model.reset()

        # create some random data
        divide_value = random.random() * (2**WIDTH_INTEGER - 0.5*2**ORDER - 1)
        divide_value_fp = int(divide_value * 2**WIDTH_MODULUS)
        dut._log.info("Test number %d, input value = %f" % (test+1, divide_value))

        # change the divide value
        model.set_divide_value(divide_value)

        # update the divider value into the DUT
        status.update()
        output_data = await new_divider_value(dut, status, divide_value_fp)
        await RisingEdge(dut.input_frequency)

        # loop through some clock cycles calculating samples
        for sample in range(NUMBER_SAMPLES):

            # check the output matches the model
            model_data = model.update()
            output_data = int(dut.output_frequency)
            assert(output_data == model_data), 'Model = %x, Simulation = %x' % (model_data, output_data)

            await RisingEdge(dut.input_frequency)


    # print and export coverage report
    coverage_db.report_coverage(dut._log.info, bins=True)
    coverage_db.export_to_xml(filename="coverage_fractional_n_divider.xml")
    coverage_db.export_to_yaml(filename="coverage_fractional_n_divider.yml")
# hardware constants # test constants Test the output against the model with random input values # create the model # create an object that views the DUT state # start clock # loop through the tests # reset the DUT # create some random data # change the divide value # update the divider value into the DUT # loop through some clock cycles calculating samples # check the output matches the model # print and export coverage report