示例#1
0
 def __init__(self, dut, num_samples, input_width):
     clk = Clock(dut.clk_i, 40)
     clk_3x = Clock(dut.clk_3x_i, 120)
     self.multiclock = MultiClock([clk, clk_3x])
     self.dut = dut
     self.re_inputs = random_samples(input_width, num_samples)
     self.im_inputs = random_samples(input_width, num_samples)
     self.outputs = np.fft.fft(self.re_inputs + 1j * self.im_inputs)
示例#2
0
 def __init__(self, dut):
     clk = Clock(dut.clk_i, 40)
     clk_7_5 = Clock(dut.clk_7_5mhz, 7.5)
     clk_120 = Clock(dut.clk_120mhz, 120)
     clk_80 = Clock(dut.clk_80mhz, 80)
     clk_20 = Clock(dut.clk_20mhz, 20)
     ftclk = Clock(dut.ft_clkout_i, 60)
     self.multiclock = MultiClock(
         [clk, clk_7_5, clk_120, clk_80, clk_20, ftclk])
     self.dut = dut
示例#3
0
class FT245_TB:
    """
    FT2232H FT245 asynchronous mode FIFO testbench class.
    """
    def __init__(self, dut):
        clk = Clock(dut.clk, 40)
        ft_clk = Clock(dut.ft_clk, 60)
        slow_ft_clk = Clock(dut.slow_ft_clk, 7.5)
        self.multiclock = MultiClock([clk, ft_clk, slow_ft_clk])
        self.dut = dut

    @cocotb.coroutine
    async def setup(self):
        self.multiclock.start_all_clocks()
        await self.reset()

    @cocotb.coroutine
    async def reset(self):
        await self.await_all_clocks()
        self.dut.rst_n <= 0
        await self.await_all_clocks()
        self.dut.rst_n <= 1

    @cocotb.coroutine
    async def await_all_clocks(self):
        trigs = []
        for clk in self.multiclock.clocks:
            trigs.append(RisingEdge(clk.clk))

        await Combine(*trigs)

    @cocotb.coroutine
    async def fpga_write_continuous(self, inputs):
        """
        Continuously write from FPGA. When inputs have been exhausted,
        write zeros.
        """
        sample_ctr = 0
        num_samples = len(inputs)
        self.dut.wren <= 1
        while True:
            if sample_ctr < num_samples:
                self.dut.wrdata <= BinaryValue(
                    int(inputs[sample_ctr].item()), 64, binaryRepresentation=2)
            else:
                self.dut.wrdata <= 0
            sample_ctr += 1
            await RisingEdge(self.dut.clk)
示例#4
0
class PllSyncCtrTB:
    def __init__(self, dut):
        fst_clk = Clock(dut.fst_clk, 80)
        slw_clk = Clock(dut.slw_clk, 10)
        self.multiclock = MultiClock([fst_clk, slw_clk])
        self.dut = dut

    @cocotb.coroutine
    async def setup(self):
        self.multiclock.start_all_clocks()
        await self.await_all_clocks()
        self.dut.rst_n <= 0
        await self.await_all_clocks()
        self.dut.rst_n <= 1

    @cocotb.coroutine
    async def await_all_clocks(self):
        trigs = []
        for clk in self.multiclock.clocks:
            trigs.append(RisingEdge(clk.clk))

        await Combine(*trigs)
示例#5
0
 def __init__(self, dut):
     rdclk = Clock(dut.rdclk, 60)
     wrclk = Clock(dut.wrclk, 40)
     self.multiclock = MultiClock([rdclk, wrclk])
     self.dut = dut
示例#6
0
class AsyncFifoTB:
    """
    Async FIFO testbench class. Used to setup, drive and monitor the
    async FIFO under test.
    """
    def __init__(self, dut):
        rdclk = Clock(dut.rdclk, 60)
        wrclk = Clock(dut.wrclk, 40)
        self.multiclock = MultiClock([rdclk, wrclk])
        self.dut = dut

    @cocotb.coroutine
    async def setup(self):
        """Startup the async FIFO."""
        self.multiclock.start_all_clocks()
        await self.reset()

    @cocotb.coroutine
    async def reset(self):
        """
        Perform a sufficiently long reset to be registered by all clock
        domains.
        """
        await self.await_all_clocks()
        self.dut.rst_n <= 0
        self.dut.rden <= 0
        self.dut.wren <= 0
        await self.await_all_clocks()
        self.dut.rst_n <= 1

    @cocotb.coroutine
    async def await_all_clocks(self):
        """
        Wait for positive edge on both clocks before proceeding.
        """
        trigs = []
        for clk in self.multiclock.clocks:
            trigs.append(RisingEdge(clk.clk))

        await Combine(*trigs)

    @cocotb.coroutine
    async def write(self, val):
        """Write a value to the FIFO."""
        await RisingEdge(self.dut.wrclk)
        self.dut.wren <= 1
        self.dut.wrdata <= val
        await RisingEdge(self.dut.wrclk)

    @cocotb.coroutine
    async def read(self):
        """Read a value from the FIFO."""
        await RisingEdge(self.dut.rdclk)
        self.dut.rden <= 1
        await RisingEdge(self.dut.rdclk)
        await ReadOnly()
        rdval = self.dut.rddata.value
        return rdval

    @cocotb.coroutine
    async def wait_n_read_cycles(self, ncycles):
        """Wait ncycles cycles for rdclk."""
        await RisingEdge(self.dut.rdclk)
        self.dut.rden <= 0
        while ncycles > 0:
            ncycles -= 1
            await RisingEdge(self.dut.rdclk)

    @cocotb.coroutine
    async def wait_n_write_cycles(self, ncycles):
        """Wait ncycles cycles for wrclk."""
        await RisingEdge(self.dut.wrclk)
        self.dut.wren <= 0
        while ncycles > 0:
            ncycles -= 1
            await RisingEdge(self.dut.wrclk)

    @cocotb.coroutine
    async def get_value(self, obj):
        """
        Return the current value of some part of the FIFO. Note that this
        does not wait for a clock edge, so care should be taken that
        the read is performed at the desired time.

        obj: The value to read (e.g. dut.wraddr)
        """
        await ReadOnly()
        return obj.value
示例#7
0
 def __init__(self, dut):
     fst_clk = Clock(dut.fst_clk, 80)
     slw_clk = Clock(dut.slw_clk, 10)
     self.multiclock = MultiClock([fst_clk, slw_clk])
     self.dut = dut
示例#8
0
 def __init__(self, dut):
     clk = Clock(dut.clk, 40)
     ft_clk = Clock(dut.ft_clk, 60)
     slow_ft_clk = Clock(dut.slow_ft_clk, 7.5)
     self.multiclock = MultiClock([clk, ft_clk, slow_ft_clk])
     self.dut = dut
示例#9
0
class FFTTB:
    """
    R22 SDF FFT testbench class.
    """
    def __init__(self, dut, num_samples, input_width):
        clk = Clock(dut.clk_i, 40)
        clk_3x = Clock(dut.clk_3x_i, 120)
        self.multiclock = MultiClock([clk, clk_3x])
        self.dut = dut
        self.re_inputs = random_samples(input_width, num_samples)
        self.im_inputs = random_samples(input_width, num_samples)
        self.outputs = np.fft.fft(self.re_inputs + 1j * self.im_inputs)

    @cocotb.coroutine
    async def setup(self):
        self.multiclock.start_all_clocks()
        await self.reset()

    @cocotb.coroutine
    async def reset(self):
        await self.await_all_clocks()
        self.dut.rst_n <= 0
        await self.await_all_clocks()
        self.dut.rst_n <= 1

    @cocotb.coroutine
    async def await_all_clocks(self):
        """
        Wait for positive edge on both clocks before proceeding.
        """
        trigs = []
        for clk in self.multiclock.clocks:
            trigs.append(RisingEdge(clk.clk))

        await Combine(*trigs)

    def check_outputs(self, tolerance):
        """
        Check that the measured outputs are within the specified tolerance
        of the actual outputs. Raise a test failure if not. If the
        tolerance is satisfied, return a tuple of the difference
        values.
        """
        bit_rev_ctr = self.dut.data_ctr_o.value.integer
        rval = self.dut.data_re_o.value.signed_integer
        rexp = np.real(self.outputs)[bit_rev_ctr].item()
        rdiff = rval - rexp
        ival = self.dut.data_im_o.value.signed_integer
        iexp = np.imag(self.outputs)[bit_rev_ctr].item()
        idiff = ival - iexp
        if abs(rval - rexp) > tolerance:
            raise TestFailure(("Actual real output differs from expected."
                               " Actual: %d, expected: %d, difference: %d."
                               " Tolerance set at %d.") %
                              (rval, rexp, rval - rexp, tolerance))

        if abs(ival - iexp) > tolerance:
            raise TestFailure(("Actual imaginary output differs from expected."
                               " Actual: %d, expected: %d, difference: %d."
                               " Tolerance set at %d.") %
                              (ival, iexp, ival - iexp, tolerance))

        return (rdiff, idiff)

    @cocotb.coroutine
    async def write_inputs(self):
        """
        Send all calculated inputs to dut.
        """
        ctr = 0
        num_samples = len(self.re_inputs)
        while True:
            if ctr < num_samples:
                self.dut.data_re_i <= self.re_inputs[ctr].item()
                self.dut.data_im_i <= self.im_inputs[ctr].item()
            else:
                self.dut.data_re_i <= 0
                self.dut.data_im_i <= 0

            await RisingEdge(self.dut.clk_i)
            ctr += 1

    @cocotb.coroutine
    async def send_intermittent_resets(self):
        """
        Randomly send reset signals to FFT.
        """
        timestep = min(self.multiclock.clock_periods())
        while True:
            self.dut.rst_n <= 1
            time_on = timestep * np.random.randint(1e2, 1e4, dtype=int)
            await Timer(time_on)
            self.dut.rst_n <= 0
            time_off = timestep * np.random.randint(1e2, 1e3, dtype=int)
            await Timer(time_off)
示例#10
0
class TopTB:
    def __init__(self, dut):
        clk = Clock(dut.clk_i, 40)
        clk_7_5 = Clock(dut.clk_7_5mhz, 7.5)
        clk_120 = Clock(dut.clk_120mhz, 120)
        clk_80 = Clock(dut.clk_80mhz, 80)
        clk_20 = Clock(dut.clk_20mhz, 20)
        ftclk = Clock(dut.ft_clkout_i, 60)
        self.multiclock = MultiClock(
            [clk, clk_7_5, clk_120, clk_80, clk_20, ftclk])
        self.dut = dut

    @cocotb.coroutine
    async def setup(self):
        self.multiclock.start_all_clocks()
        self.dut.ft_rxf_n_i <= 1
        self.dut.ft_txe_n_i <= 1
        self.dut.ft_suspend_n_i <= 1
        await self.reset()

    @cocotb.coroutine
    async def reset(self):
        await self.await_all_clocks()
        self.dut.pll_lock <= 0
        await self.await_all_clocks()
        self.dut.pll_lock <= 1

    @cocotb.coroutine
    async def await_all_clocks(self):
        trigs = []
        for clk in self.multiclock.clocks:
            trigs.append(RisingEdge(clk.clk))

        await Combine(*trigs)

    @cocotb.coroutine
    async def rand_lose_lock(self):
        """
        Simulate random loss of PLL lock. This attempts to be somewhat
        physically accurate by mainting the lock for longer periods
        than it is lost.
        """
        time_unit = min(self.multiclock.clock_periods())
        while True:
            time_on = np.random.randint(1e3 * time_unit,
                                        1e4 * time_unit,
                                        dtype=int)
            await Timer(time_on)
            self.dut.pll_lock <= 0
            time_off = np.random.randint(1e1 * time_unit,
                                         1e2 * time_unit,
                                         dtype=int)
            await Timer(time_off)
            self.dut.pll_lock <= 1

    @cocotb.coroutine
    async def pc_request_mode(self, mode):
        """
        Simulate sending a request from the host PC for a certain kind of
        data. This is equivalent to using the fmcw -i flag. The valid
        values are the same. I.e. @mode can be 'raw', 'fir', 'window',
        or 'fft'.
        """
        if mode == "fft":
            mode_bits = 1
        elif mode == "window":
            mode_bits = 2
        elif mode == "fir":
            mode_bits = 3
        elif mode == "raw":
            mode_bits = 4
        else:
            raise ValueError("request_mode: invalid request")

        await RisingEdge(self.dut.ft_clkout_i)
        self.dut.ft_rxf_n_i <= 0
        self.dut.ft_data_io <= mode_bits
        await RisingEdge(self.dut.ft_clkout_i)
        self.dut.ft_data_io <= mode_bits
        await RisingEdge(self.dut.ft_clkout_i)
        self.dut.ft_data_io <= mode_bits
        await RisingEdge(self.dut.ft_clkout_i)
        await RisingEdge(self.dut.ft_clkout_i)
        await ReadOnly()
        while self.dut.ft_rd_n_o.value.integer:
            await RisingEdge(self.dut.ft_clkout_i)
            await ReadOnly()
        await RisingEdge(self.dut.ft_clkout_i)
        self.dut.ft_rxf_n_i <= 1

    @cocotb.coroutine
    async def pc_request_data(self):
        """
        Signal the PC is asking to read data from the FPGA.
        """
        await RisingEdge(self.dut.ft_clkout_i)
        self.dut.ft_txe_n_i <= 0
        await RisingEdge(self.dut.ft_clkout_i)

    @cocotb.coroutine
    # TODO add samples on falling edge for chan b
    async def gen_samples(self, inputs):
        sample_ctr = 0
        num_samples = len(inputs)
        while True:
            if sample_ctr == num_samples:
                sample_ctr = 0

            self.dut.adc_d_i <= BinaryValue(
                int(inputs[sample_ctr].item()), 12, binaryRepresentation=2)
            sample_ctr += 1
            await RisingEdge(self.dut.clk_i)