diff --git a/fpga/common/rtl/tdma_scheduler.v b/fpga/common/rtl/tdma_scheduler.v new file mode 100644 index 000000000..02e2b8438 --- /dev/null +++ b/fpga/common/rtl/tdma_scheduler.v @@ -0,0 +1,383 @@ +/* + +Copyright 2019, The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS OF THE UNIVERSITY OF CALIFORNIA ''AS +IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF CALIFORNIA OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of The Regents of the University of California. + +*/ + +// Language: Verilog 2001 + +`timescale 1ns / 1ps + +/* + * TDMA scheduler module + */ +module tdma_scheduler # +( + parameter INDEX_WIDTH = 8, + parameter SCHEDULE_START_S = 48'h0, + parameter SCHEDULE_START_NS = 30'h0, + parameter SCHEDULE_PERIOD_S = 48'd0, + parameter SCHEDULE_PERIOD_NS = 30'd1000000, + parameter TIMESLOT_PERIOD_S = 48'd0, + parameter TIMESLOT_PERIOD_NS = 30'd100000, + parameter ACTIVE_PERIOD_S = 48'd0, + parameter ACTIVE_PERIOD_NS = 30'd100000 +) +( + input wire clk, + input wire rst, + + /* + * Timestamp input from PTP clock + */ + input wire [95:0] input_ts_96, + input wire input_ts_step, + + /* + * Control + */ + input wire enable, + input wire [79:0] input_schedule_start, + input wire input_schedule_start_valid, + input wire [79:0] input_schedule_period, + input wire input_schedule_period_valid, + input wire [79:0] input_timeslot_period, + input wire input_timeslot_period_valid, + input wire [79:0] input_active_period, + input wire input_active_period_valid, + + /* + * Status + */ + output wire locked, + output wire error, + + /* + * TDMA schedule outputs + */ + output wire schedule_start, + output wire [INDEX_WIDTH-1:0] timeslot_index, + output wire timeslot_start, + output wire timeslot_end, + output wire timeslot_active +); + +/* + + schedule + start + | + V + |<-------- schedule period -------->| + -----+--------+--------+--------+--------+--------+--- + | SLOT 0 | SLOT 1 | SLOT 2 | SLOT 3 | SLOT 0 | + -----+--------+--------+--------+--------+--------+--- + |<------>| + timeslot + period + + + |<-------- timeslot period -------->| + -----+-----------------------------------+------------ + | SLOT 0 | SLOT 1 + -----+-----------------------------------+------------ + |<---- active period ----->| + +*/ + +localparam [2:0] + STATE_IDLE = 3'd0, + STATE_UPDATE_SCHEDULE_1 = 3'd1, + STATE_UPDATE_SCHEDULE_2 = 3'd2, + STATE_UPDATE_SLOT_1 = 3'd3, + STATE_UPDATE_SLOT_2 = 3'd4, + STATE_UPDATE_SLOT_3 = 3'd5, + STATE_WAIT = 3'd6; + +reg [2:0] state_reg = STATE_IDLE, state_next; + +reg [47:0] time_s_reg = 0; +reg [30:0] time_ns_reg = 0; + +reg [47:0] first_slot_s_reg = 0, first_slot_s_next; +reg [30:0] first_slot_ns_reg = 0, first_slot_ns_next; + +reg [47:0] next_slot_s_reg = 0, next_slot_s_next; +reg [30:0] next_slot_ns_reg = 0, next_slot_ns_next; + +reg [47:0] active_end_s_reg = 0, active_end_s_next; +reg [30:0] active_end_ns_reg = 0, active_end_ns_next; + +reg [47:0] schedule_start_s_reg = SCHEDULE_START_S; +reg [30:0] schedule_start_ns_reg = SCHEDULE_START_NS; + +reg [47:0] schedule_period_s_reg = SCHEDULE_PERIOD_S; +reg [30:0] schedule_period_ns_reg = SCHEDULE_PERIOD_NS; + +reg [47:0] timeslot_period_s_reg = TIMESLOT_PERIOD_S; +reg [30:0] timeslot_period_ns_reg = TIMESLOT_PERIOD_NS; + +reg [47:0] active_period_s_reg = ACTIVE_PERIOD_S; +reg [30:0] active_period_ns_reg = ACTIVE_PERIOD_NS; + +reg [29:0] ts_ns_inc_reg = 0, ts_ns_inc_next; +reg [30:0] ts_ns_ovf_reg = 0, ts_ns_ovf_next; + +reg locked_reg = 1'b0; +reg error_reg = 1'b0; +reg output_reg = 1'b0, output_next; + +reg schedule_start_reg = 1'b0, schedule_start_next; +reg [INDEX_WIDTH-1:0] timeslot_index_reg = 0, timeslot_index_next; +reg timeslot_start_reg = 1'b0, timeslot_start_next; +reg timeslot_end_reg = 1'b0, timeslot_end_next; +reg timeslot_active_reg = 1'b0, timeslot_active_next; + +assign locked = locked_reg; +assign error = error_reg; + +assign schedule_start = schedule_start_reg; +assign timeslot_index = timeslot_index_reg; +assign timeslot_start = timeslot_start_reg; +assign timeslot_end = timeslot_end_reg; +assign timeslot_active = timeslot_active_reg; + +always @* begin + state_next = STATE_IDLE; + + first_slot_s_next = first_slot_s_reg; + first_slot_ns_next = first_slot_ns_reg; + + next_slot_s_next = next_slot_s_reg; + next_slot_ns_next = next_slot_ns_reg; + + active_end_s_next = active_end_s_reg; + active_end_ns_next = active_end_ns_reg; + + ts_ns_inc_next = ts_ns_inc_reg; + + ts_ns_ovf_next = ts_ns_ovf_reg; + + schedule_start_next = 1'b0; + timeslot_index_next = timeslot_index_reg; + timeslot_start_next = 1'b0; + timeslot_end_next = 1'b0; + timeslot_active_next = timeslot_active_reg; + + case (state_reg) + STATE_IDLE: begin + // set next rise to start time + first_slot_s_next = schedule_start_s_reg; + first_slot_ns_next = schedule_start_ns_reg; + next_slot_s_next = schedule_start_s_reg; + next_slot_ns_next = schedule_start_ns_reg; + if (input_schedule_start_valid || input_schedule_period_valid) begin + state_next = STATE_IDLE; + end else begin + state_next = STATE_WAIT; + end + end + STATE_UPDATE_SCHEDULE_1: begin + // set next schedule start time to next schedule start time plus schedule period + ts_ns_inc_next = first_slot_ns_reg + schedule_period_ns_reg; + ts_ns_ovf_next = first_slot_ns_reg + schedule_period_ns_reg - 31'd1_000_000_000; + if (input_schedule_start_valid || input_schedule_period_valid) begin + state_next = STATE_IDLE; + end else begin + state_next = STATE_UPDATE_SCHEDULE_2; + end + end + STATE_UPDATE_SCHEDULE_2: begin + if (!ts_ns_ovf_reg[30]) begin + // if the overflow lookahead did not borrow, one second has elapsed + first_slot_s_next = first_slot_s_reg + schedule_period_s_reg + 1; + first_slot_ns_next = ts_ns_ovf_reg; + end else begin + // no increment seconds field + first_slot_s_next = first_slot_s_reg + schedule_period_s_reg; + first_slot_ns_next = ts_ns_inc_reg; + end + next_slot_s_next = first_slot_s_reg; + next_slot_ns_next = first_slot_ns_reg; + if (input_schedule_start_valid || input_schedule_period_valid) begin + state_next = STATE_IDLE; + end else begin + state_next = STATE_UPDATE_SLOT_1; + end + end + STATE_UPDATE_SLOT_1: begin + // set next fall time to next rise time plus width + ts_ns_inc_next = next_slot_ns_reg + active_period_ns_reg; + ts_ns_ovf_next = next_slot_ns_reg + active_period_ns_reg - 31'd1_000_000_000; + if (input_schedule_start_valid || input_schedule_period_valid) begin + state_next = STATE_IDLE; + end else begin + state_next = STATE_UPDATE_SLOT_2; + end + end + STATE_UPDATE_SLOT_2: begin + if (!ts_ns_ovf_reg[30]) begin + // if the overflow lookahead did not borrow, one second has elapsed + active_end_s_next = next_slot_s_reg + active_period_s_reg + 1; + active_end_ns_next = ts_ns_ovf_reg; + end else begin + // no increment seconds field + active_end_s_next = next_slot_s_reg + active_period_s_reg; + active_end_ns_next = ts_ns_inc_reg; + end + // set next timeslot start time to next timeslot start time plus timeslot period + ts_ns_inc_next = next_slot_ns_reg + timeslot_period_ns_reg; + ts_ns_ovf_next = next_slot_ns_reg + timeslot_period_ns_reg - 31'd1_000_000_000; + if (input_schedule_start_valid || input_schedule_period_valid) begin + state_next = STATE_IDLE; + end else begin + state_next = STATE_UPDATE_SLOT_3; + end + end + STATE_UPDATE_SLOT_3: begin + if (!ts_ns_ovf_reg[30]) begin + // if the overflow lookahead did not borrow, one second has elapsed + next_slot_s_next = next_slot_s_reg + timeslot_period_s_reg + 1; + next_slot_ns_next = ts_ns_ovf_reg; + end else begin + // no increment seconds field + next_slot_s_next = next_slot_s_reg + timeslot_period_s_reg; + next_slot_ns_next = ts_ns_inc_reg; + end + if (input_schedule_start_valid || input_schedule_period_valid) begin + state_next = STATE_IDLE; + end else begin + state_next = STATE_WAIT; + end + end + STATE_WAIT: begin + if (input_schedule_start_valid || input_schedule_period_valid) begin + state_next = STATE_IDLE; + end else if ((time_s_reg > first_slot_s_reg) || (time_s_reg == first_slot_s_reg && time_ns_reg > first_slot_ns_reg)) begin + // start of next schedule period + schedule_start_next = enable; + timeslot_index_next = 0; + timeslot_start_next = enable; + timeslot_end_next = timeslot_active_reg && enable; + timeslot_active_next = enable; + state_next = STATE_UPDATE_SCHEDULE_1; + end else if ((time_s_reg > next_slot_s_reg) || (time_s_reg == next_slot_s_reg && time_ns_reg > next_slot_ns_reg)) begin + // start of next timeslot + timeslot_index_next = timeslot_index_reg + 1; + timeslot_start_next = enable; + timeslot_end_next = timeslot_active_reg && enable; + timeslot_active_next = enable; + state_next = STATE_UPDATE_SLOT_1; + end else if (timeslot_active_reg && ((time_s_reg > active_end_s_reg) || (time_s_reg == active_end_s_reg && time_ns_reg > active_end_ns_reg))) begin + // start of next timeslot + timeslot_end_next = enable; + timeslot_active_next = 1'b0; + state_next = STATE_WAIT; + end else begin + state_next = STATE_WAIT; + end + end + endcase +end + +always @(posedge clk) begin + state_reg <= state_next; + + time_s_reg <= input_ts_96[95:48]; + time_ns_reg <= input_ts_96[45:16]; + + if (input_schedule_start_valid) begin + schedule_start_s_reg <= input_schedule_start[79:32]; + schedule_start_ns_reg <= input_schedule_start[31:0]; + end + + if (input_schedule_period_valid) begin + schedule_period_s_reg <= input_schedule_period[79:32]; + schedule_period_ns_reg <= input_schedule_period[31:0]; + end + + if (input_timeslot_period_valid) begin + timeslot_period_s_reg <= input_timeslot_period[79:32]; + timeslot_period_ns_reg <= input_timeslot_period[31:0]; + end + + if (input_active_period_valid) begin + active_period_s_reg <= input_active_period[79:32]; + active_period_ns_reg <= input_active_period[31:0]; + end + + first_slot_s_reg <= first_slot_s_next; + first_slot_ns_reg <= first_slot_ns_next; + + next_slot_s_reg <= next_slot_s_next; + next_slot_ns_reg <= next_slot_ns_next; + + active_end_s_reg <= active_end_s_next; + active_end_ns_reg <= active_end_ns_next; + + ts_ns_inc_reg <= ts_ns_inc_next; + ts_ns_ovf_reg <= ts_ns_ovf_next; + + schedule_start_reg <= schedule_start_next; + timeslot_index_reg <= timeslot_index_next; + timeslot_start_reg <= timeslot_start_next; + timeslot_end_reg <= timeslot_end_next; + timeslot_active_reg <= timeslot_active_next; + + if (rst) begin + state_reg <= STATE_IDLE; + + time_s_reg <= 0; + time_ns_reg <= 0; + + schedule_start_s_reg <= SCHEDULE_START_S; + schedule_start_ns_reg <= SCHEDULE_START_NS; + + schedule_period_s_reg <= SCHEDULE_PERIOD_S; + schedule_period_ns_reg <= SCHEDULE_PERIOD_NS; + + timeslot_period_s_reg <= TIMESLOT_PERIOD_S; + timeslot_period_ns_reg <= TIMESLOT_PERIOD_NS; + + active_period_s_reg <= ACTIVE_PERIOD_S; + active_period_ns_reg <= ACTIVE_PERIOD_NS; + + locked_reg <= 1'b0; + error_reg <= 1'b0; + + schedule_start_reg <= 1'b0; + timeslot_index_reg <= 0; + timeslot_start_reg <= 1'b0; + timeslot_end_reg <= 1'b0; + timeslot_active_reg <= 1'b0; + end +end + +endmodule diff --git a/fpga/common/tb/test_tdma_scheduler.py b/fpga/common/tb/test_tdma_scheduler.py new file mode 100755 index 000000000..75499918b --- /dev/null +++ b/fpga/common/tb/test_tdma_scheduler.py @@ -0,0 +1,180 @@ +#!/usr/bin/env python +""" + +Copyright 2019, The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS OF THE UNIVERSITY OF CALIFORNIA ''AS +IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF CALIFORNIA OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of The Regents of the University of California. + +""" + +from myhdl import * +import os + +import ptp + +module = 'tdma_scheduler' +testbench = 'test_%s' % module + +srcs = [] + +srcs.append("../rtl/%s.v" % module) +srcs.append("%s.v" % testbench) + +src = ' '.join(srcs) + +build_cmd = "iverilog -o %s.vvp %s" % (testbench, src) + +def bench(): + + # Parameters + INDEX_WIDTH = 8 + SCHEDULE_START_S = 0x0 + SCHEDULE_START_NS = 0x0 + SCHEDULE_PERIOD_S = 0 + SCHEDULE_PERIOD_NS = 1000000 + TIMESLOT_PERIOD_S = 0 + TIMESLOT_PERIOD_NS = 100000 + + # Inputs + clk = Signal(bool(0)) + rst = Signal(bool(0)) + current_test = Signal(intbv(0)[8:]) + + input_ts_96 = Signal(intbv(0)[96:]) + input_ts_step = Signal(bool(0)) + enable = Signal(bool(0)) + input_schedule_start = Signal(intbv(0)[80:]) + input_schedule_start_valid = Signal(bool(0)) + input_schedule_period = Signal(intbv(0)[80:]) + input_schedule_period_valid = Signal(bool(0)) + input_timeslot_period = Signal(intbv(0)[80:]) + input_timeslot_period_valid = Signal(bool(0)) + input_active_period = Signal(intbv(0)[80:]) + input_active_period_valid = Signal(bool(0)) + + # Outputs + locked = Signal(bool(0)) + error = Signal(bool(0)) + schedule_start = Signal(bool(0)) + timeslot_index = Signal(intbv(0)[INDEX_WIDTH:]) + timeslot_start = Signal(bool(0)) + timeslot_end = Signal(bool(0)) + timeslot_active = Signal(bool(0)) + + # PTP clock + ptp_clock = ptp.PtpClock() + + ptp_logic = ptp_clock.create_logic( + clk, + rst, + ts_96=input_ts_96 + ) + + # DUT + if os.system(build_cmd): + raise Exception("Error running build command") + + dut = Cosimulation( + "vvp -m myhdl %s.vvp -lxt2" % testbench, + clk=clk, + rst=rst, + current_test=current_test, + input_ts_96=input_ts_96, + input_ts_step=input_ts_step, + enable=enable, + input_schedule_start=input_schedule_start, + input_schedule_start_valid=input_schedule_start_valid, + input_schedule_period=input_schedule_period, + input_schedule_period_valid=input_schedule_period_valid, + input_timeslot_period=input_timeslot_period, + input_timeslot_period_valid=input_timeslot_period_valid, + input_active_period=input_active_period, + input_active_period_valid=input_active_period_valid, + locked=locked, + error=error, + schedule_start=schedule_start, + timeslot_index=timeslot_index, + timeslot_start=timeslot_start, + timeslot_end=timeslot_end, + timeslot_active=timeslot_active + ) + + @always(delay(4)) + def clkgen(): + clk.next = not clk + + @instance + def check(): + yield delay(100) + yield clk.posedge + rst.next = 1 + yield clk.posedge + rst.next = 0 + yield clk.posedge + yield delay(100) + yield clk.posedge + + # testbench stimulus + + enable.next = 1 + + yield clk.posedge + print("test 1: Test pulse out") + current_test.next = 1 + + input_schedule_start.next = 1000 + input_schedule_start_valid.next = 1 + input_schedule_period.next = 2000 + input_schedule_period_valid.next = 1 + input_timeslot_period.next = 400 + input_timeslot_period_valid.next = 1 + input_active_period.next = 300 + input_active_period_valid.next = 1 + + yield clk.posedge + + input_schedule_start_valid.next = 0 + input_schedule_period_valid.next = 0 + input_timeslot_period_valid.next = 0 + input_active_period_valid.next = 0 + + yield delay(10000) + + yield delay(100) + + raise StopSimulation + + return instances() + +def test_bench(): + sim = Simulation(bench()) + sim.run() + +if __name__ == '__main__': + print("Running test...") + test_bench() diff --git a/fpga/common/tb/test_tdma_scheduler.v b/fpga/common/tb/test_tdma_scheduler.v new file mode 100644 index 000000000..4f2310971 --- /dev/null +++ b/fpga/common/tb/test_tdma_scheduler.v @@ -0,0 +1,147 @@ +/* + +Copyright 2019, The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS OF THE UNIVERSITY OF CALIFORNIA ''AS +IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF CALIFORNIA OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of The Regents of the University of California. + +*/ + +// Language: Verilog 2001 + +`timescale 1ns / 1ps + +/* + * Testbench for tdma_scheduler + */ +module test_tdma_scheduler; + +// Parameters +parameter INDEX_WIDTH = 8; +parameter SCHEDULE_START_S = 48'h0; +parameter SCHEDULE_START_NS = 30'h0; +parameter SCHEDULE_PERIOD_S = 48'd0; +parameter SCHEDULE_PERIOD_NS = 30'd1000000; +parameter TIMESLOT_PERIOD_S = 48'd0; +parameter TIMESLOT_PERIOD_NS = 30'd100000; +parameter ACTIVE_PERIOD_S = 48'd0; +parameter ACTIVE_PERIOD_NS = 30'd100000; + +// Inputs +reg clk = 0; +reg rst = 0; +reg [7:0] current_test = 0; + +reg [95:0] input_ts_96 = 0; +reg input_ts_step = 0; +reg enable = 0; +reg [79:0] input_schedule_start = 0; +reg input_schedule_start_valid = 0; +reg [79:0] input_schedule_period = 0; +reg input_schedule_period_valid = 0; +reg [79:0] input_timeslot_period = 0; +reg input_timeslot_period_valid = 0; +reg [79:0] input_active_period = 0; +reg input_active_period_valid = 0; + +// Outputs +wire locked; +wire error; +wire schedule_start; +wire [INDEX_WIDTH-1:0] timeslot_index; +wire timeslot_start; +wire timeslot_end; +wire timeslot_active; + +initial begin + // myhdl integration + $from_myhdl( + clk, + rst, + current_test, + input_ts_96, + input_ts_step, + enable, + input_schedule_start, + input_schedule_start_valid, + input_schedule_period, + input_schedule_period_valid, + input_timeslot_period, + input_timeslot_period_valid, + input_active_period, + input_active_period_valid + ); + $to_myhdl( + locked, + error, + schedule_start, + timeslot_index, + timeslot_start, + timeslot_end, + timeslot_active + ); + + // dump file + $dumpfile("test_tdma_scheduler.lxt"); + $dumpvars(0, test_tdma_scheduler); +end + +tdma_scheduler #( + .INDEX_WIDTH(INDEX_WIDTH), + .SCHEDULE_START_S(SCHEDULE_START_S), + .SCHEDULE_START_NS(SCHEDULE_START_NS), + .SCHEDULE_PERIOD_S(SCHEDULE_PERIOD_S), + .SCHEDULE_PERIOD_NS(SCHEDULE_PERIOD_NS), + .TIMESLOT_PERIOD_S(TIMESLOT_PERIOD_S), + .TIMESLOT_PERIOD_NS(TIMESLOT_PERIOD_NS), + .ACTIVE_PERIOD_S(ACTIVE_PERIOD_S), + .ACTIVE_PERIOD_NS(ACTIVE_PERIOD_NS) +) +UUT ( + .clk(clk), + .rst(rst), + .input_ts_96(input_ts_96), + .input_ts_step(input_ts_step), + .enable(enable), + .input_schedule_start(input_schedule_start), + .input_schedule_start_valid(input_schedule_start_valid), + .input_schedule_period(input_schedule_period), + .input_schedule_period_valid(input_schedule_period_valid), + .input_timeslot_period(input_timeslot_period), + .input_timeslot_period_valid(input_timeslot_period_valid), + .input_active_period(input_active_period), + .input_active_period_valid(input_active_period_valid), + .locked(locked), + .error(error), + .schedule_start(schedule_start), + .timeslot_index(timeslot_index), + .timeslot_start(timeslot_start), + .timeslot_end(timeslot_end), + .timeslot_active(timeslot_active) +); + +endmodule