mirror of
https://github.com/corundum/corundum.git
synced 2025-01-16 08:12:53 +08:00
Add TDMA scheduler module and testbench
This commit is contained in:
parent
fc9a6c1c50
commit
a653f2d839
383
fpga/common/rtl/tdma_scheduler.v
Normal file
383
fpga/common/rtl/tdma_scheduler.v
Normal file
@ -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
|
180
fpga/common/tb/test_tdma_scheduler.py
Executable file
180
fpga/common/tb/test_tdma_scheduler.py
Executable file
@ -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()
|
147
fpga/common/tb/test_tdma_scheduler.v
Normal file
147
fpga/common/tb/test_tdma_scheduler.v
Normal file
@ -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
|
Loading…
x
Reference in New Issue
Block a user