0% found this document useful (0 votes)
1K views104 pages

Design and Verification of A Round-Robin Arbiter

This paper describes the design and verification of a weighted round-robin arbiter. The arbiter allows requestors to have weighted access to shared resources by quantizing time shares based on programmable weights. It consists of a weight decoder, next grant precalculator, and grant state machine. The design is verified using SystemVerilog by modeling requestors, generating random inputs, running a software model for prediction, and collecting coverage metrics. Simulation shows the arbiter operates as intended. Verification results indicate no issues and the arbiter incurs modest area and power overhead. The paper concludes the arbiter provides a fair and customizable arbitration scheme.

Uploaded by

koorapatisagar
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
1K views104 pages

Design and Verification of A Round-Robin Arbiter

This paper describes the design and verification of a weighted round-robin arbiter. The arbiter allows requestors to have weighted access to shared resources by quantizing time shares based on programmable weights. It consists of a weight decoder, next grant precalculator, and grant state machine. The design is verified using SystemVerilog by modeling requestors, generating random inputs, running a software model for prediction, and collecting coverage metrics. Simulation shows the arbiter operates as intended. Verification results indicate no issues and the arbiter incurs modest area and power overhead. The paper concludes the arbiter provides a fair and customizable arbitration scheme.

Uploaded by

koorapatisagar
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 104

Rochester Institute of Technology

RIT Scholar Works


Theses Thesis/Dissertation Collections

8-2018

Design and Verification of a Round-Robin Arbiter


Aung Toe
[email protected]

Follow this and additional works at: http://scholarworks.rit.edu/theses

Recommended Citation
Toe, Aung, "Design and Verification of a Round-Robin Arbiter" (2018). Thesis. Rochester Institute of Technology. Accessed from

This Master's Project is brought to you for free and open access by the Thesis/Dissertation Collections at RIT Scholar Works. It has been accepted for
inclusion in Theses by an authorized administrator of RIT Scholar Works. For more information, please contact [email protected].
Design and verification of a Round-Robin Arbiter

by
Aung Toe

Graduate Paper

Submitted in partial fulfillment


of the requirements for the degree of
Master of Science
in Electrical Engineering

Approved by:

Mr. Mark A. Indovina, Lecturer


Graduate Research Advisor, Department of Electrical and Microelectronic Engineering

Dr. Sohail A. Dianat, Professor


Department Head, Department of Electrical and Microelectronic Engineering

Department of Electrical and Microelectronic Engineering


Kate Gleason College of Engineering
Rochester Institute of Technology
Rochester, New York
August 2018
To my family and friends, for all of their endless love, support, and encouragement.
Abstract

As the number of bus masters increases in chip, the performance of a system largely depends
on the arbitration scheme. The throughput of the system is affected by the arbiter circuit
which controls the grant for various requestors. An arbitration scheme is usually chosen
based on the application. A memory arbiter decides which CPU will get access for each
cycle. A packet switch uses an arbiter to decide which input packet will be scheduled to
the output. This paper introduces a Round-robin arbitration with adjustable weight of
resource access time. The Round-robin arbiter mechanism is useful when no starvation
of grants is allowed. The arbiter quantizes time shares each requestor is allowed to have.
A minimal fairness is guaranteed by granting requestors in Round-robin manner. The
requestors can prioritize their time shares by the weight. For example, if requestor A has
a weight of two and requestor B has a weight of four, arbiter will allocate requestor B with
time slice two times longer than that of requestor A’s. The verification of the design is
carried out using SystemVerilog. The inputs of the arbiter are randomized, outputs are
predicted in a software model and verification coverage is collected. The work in this paper
includes design and verification of a weighted Round-robin arbiter.
Declaration

I hereby declare that except where specific reference is made to the work of others, the
contents of this paper are original and have not been submitted in whole or in part for
consideration for any other degree or qualification in this, or any other University. This
paper is the result of my own work and includes nothing which is the outcome of work
done in collaboration, except where specifically indicated in the text.

Aung Toe
August 2018
Acknowledgements

Foremost, I would like to express my sincere gratitude to my advisor/mentor, Mark A.


Indovina, for the continuous support throughout the project. Under his mentor-ship, not
only did I learn to love complex digital systems but also to become a good engineer.
I would also like to thank my professor, Dorin Patru, for introducing me to various prac-
tical design concepts during my coursework at Rochester Institute of Technology (RIT).
My sincere thanks to all my friends who shared my journey at RIT for the sleepless
nights working together before deadlines.
Last but not least, I want to thank David Coumou, Aaron Radomski and Daniel Gill
for their patience and guidance in my career development.
Contents

Abstract ii

Declaration iii

Acknowledgements iv

Contents v

List of Figures vii

List of Listings viii

List of Tables ix

1 Introduction 1
1.1 Organization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

2 Background Research 4
2.1 Fixed Priority Arbitration . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.2 Lottery Arbiter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.3 Matrix Arbiter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

3 Weighted Round-Robin Arbiter 9


3.1 Weight Decoder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.2 Next Grant Precalculator . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.3 Grant State Machine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

4 SystemVerilog Verification Design 16


4.1 Requestor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
4.2 Generator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
4.3 Agent . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
4.4 Driver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
4.5 Monitor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
Contents vi

4.6 Checker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
4.7 Scoreboard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
4.8 Determinism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

5 Tests and Results 23


5.1 Simulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
5.1.1 Weight Decoder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
5.1.2 Next Grant PreCalculator . . . . . . . . . . . . . . . . . . . . . . . 24
5.1.3 Round-Robin Top Level/Grant State Machine . . . . . . . . . . . . 24
5.2 SystemVerilog Verification Results . . . . . . . . . . . . . . . . . . . . . . . 24
5.2.1 Scoreboard scores . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
5.3 System Overhead . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
5.3.1 Area Overhead . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
5.3.2 Power Overhead . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

6 Conclusions 28
6.1 Future Work . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

References 30

I Arbiter Source Code I-1

II Test Bench Source Code II-35


List of Figures

2.1 Lottery Manager [1] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6


2.2 Priority Matrix[2] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.3 Matrix Transition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

3.1 Packet Switching Architecture . . . . . . . . . . . . . . . . . . . . . . . . . 10


3.2 Weight Bus Size . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3.3 One-hot Index Flowchart . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.4 Next Grant PreCalculator . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.5 NGPRC Calculation Steps . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
3.6 Grant State Machine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

4.1 SystemVerilog Environment . . . . . . . . . . . . . . . . . . . . . . . . . . 18


4.2 Function Coverage Loop [3] . . . . . . . . . . . . . . . . . . . . . . . . . . 19

5.1 Weight Decoder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23


5.2 Next Grant PreCalculator . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
5.3 Top Level Simulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
List of Listings

I.1 Weight Decoder Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . I-1


I.2 Weight Decoder Test Module . . . . . . . . . . . . . . . . . . . . . . . . . I-4
I.3 Next Grant Precalculator Module . . . . . . . . . . . . . . . . . . . . . . . I-8
I.4 Next Grant Precalculator Test Module . . . . . . . . . . . . . . . . . . . . I-13
I.5 Grant Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . I-21
I.6 Round Robin Arbiter Module . . . . . . . . . . . . . . . . . . . . . . . . . I-27
I.7 Round Robin Arbiter Test Module . . . . . . . . . . . . . . . . . . . . . . I-31

II.1 Requestor Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . II-35


II.2 Generator Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . II-37
II.3 Agent Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . II-39
II.4 Driver Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . II-42
II.5 Monitor Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . II-45
II.6 Checker Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . II-49
II.7 Scoreboard Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . II-52
II.8 Assertion Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . II-53
II.9 Interface Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . II-54
II.10 Environment Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . II-55
II.11 TopLevel Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . II-56
II.12 TestCase Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . II-57
List of Tables

5.1 SystemVerilog Verification Hit Scores . . . . . . . . . . . . . . . . . . . . . 25


5.2 Area Overhead . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
5.3 Power Overhead . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
Chapter 1

Introduction

Scheduling algorithms are required when multiple requestors require access to a shared
resource. In a System on Chip (SoC), multiple devices in the chip are needed to work
together. As a result, an SoC may have multiple bus masters. A fast and powerful arbiter
becomes important to service all the bus masters. Another example of arbitration system
application is network switches. In a network switch, packets from multiple input ports
need to go through a single output port[4, 5]. As the number of parallel processes increases,
accessing a shared resource becomes the bottleneck in performance[6]. One of the goals
of a scheduler is to maximize throughput. The throughput of a system can be maximized
by minimizing wait time for each request. The advantages of utilizing arbiters include
access fairness for the requestors to the resources, utilization without wasting cycles, re-
usability, arbitration speed, power and resource overhead[7, 8]. Different types of Round-
robin arbiters such as baseline arbiters, time speculative arbiters, acyclic arbiters, parallel
prefix arbiters, priority based arbiters, etc... are used in various applications[9].
In the case of multiple bus masters, all masters require access to a shared resource
at the same or similar level of priority. A Round-robin arbitration mechanism fits the
1.1 Organization 2

application of fairness without starving the requestors. A Round-robin arbiter allocates


fixed time slices for the masters for each Round-robin turn. This time slice limitation
allows the predictability of worst-case time when the grant will get granted[10].
In this paper, a Round-robin arbiter is designed using weight decoder, next grant pre-
calculate logic and granting logic. The weight of each granted requestor is decoded using a
weight decoder logic. Based on the current grant, the next possible grant is precalculated in
Round-robin mechanism. Finally, the granting logic checks for requests and precalculated
next grant mask to select a single grant.
Weight decoder, next grant precalculator and grant state-machine are designed to be
configurable. The number of requestors and the bit width of the weight can be set before
synthesis. The request inputs and grant outputs are in one-hot format. The weights
requested by requestors are concatenated in a weight bus. The weight decoder logic dictates
the grant logic how long each grant is needed for each request. The next grant calculator
algorithm enforces the grant logic to be in Round-robin order. The calculator acts like a
record book to keep track of current grant and next possible grants. Every clock cycle, the
grant logic state-machine services appropriate grant by checking the weight, current grant,
requests and precalculated next grant.

1.1 Organization

This paper is organized as follows:

• Chapter 2 discusses different arbitration algorithms.

• Chapter 3 discusses the design and implementation of weighted Round-robin arbiter.

• Chapter 4 discusses the design and implementation of SystemVerilog verification.


1.1 Organization 3

• Chapter 5 discusses the test results and statistics of 8 port arbiter.

• Chapter 6 is the conclusion and possible future work.


Chapter 2

Background Research

Arbiters play an important role when multiple requests are sent to access a single resource.
In a network switching router, the packets received on input ports are sent out to the
respective output ports. The arbiter acts a middle man to direct which input gets to send
its packet to the designated output. The arbitration speed of the arbiter has a large factor
in determining the speed of switching performance. Of the many metrics to benchmark
an arbiter, fairness is a good unit to measure the performance, and there are a few types
typically utilized:

• Weak Fairness

• Weighted Fairness

• Last Served Lowest Priority (LSLP)

Weak Fairness means a request may have to wait indefinitely until it gets served. There
may be higher priority requestors holding on to the grant. Section 2.1 discusses a Fixed
Priority Arbiter that demonstrates the weak fairness metric. The Lottery Arbiter discussed
in Section 2.2 updates the weight of the lottery ticket as it arbitrates. The weight of the
2.1 Fixed Priority Arbitration 5

ticket increases the chances of winning the grant. This algorithm has the property of
Weighted Fairness. The Matrix Arbiter in Section 2.3 has the property of LSLP. The last
served requestor will have the lowest priority in the arbiter.

2.1 Fixed Priority Arbitration

Fixed priority arbiter is the simplest form of arbiter. It is also known as per-emptive arbiter
due to the nature of its scheduling algorithm. Each master is given a priority from high to
low. As shown in Eqn 2.1, master i − 1 has higher priority than master i[7, 9]. For master
i to get the grant, all the masters higher priority than master i must not be requesting to
the arbiter.

granti = req0 · req1 · req2 · · · reqi−1 · reqi (2.1)

For example, if there are 3 masters, master 0 is given priority 0, master 1 priority 1 and
master 2 priority 2. Grant is given to the master that has the highest priority. If master
0 and master 1 request at the same time, master 0 will get the grant since it has higher
priority. As a result, a higher priority master can starve other masters by monopolizing
the bus. However, due to the simplicity of the design, fixed priority arbiters are very useful
in applications where high priority tasks need immediate servicing and low priority tasks
can wait indefinitely to get grant.

2.2 Lottery Arbiter

Lottery arbitration scheduling is based on the weighted probabilistic distributions. The


algorithm utilizes a lottery manager to mange the drawing of grants. As in Figure 2.1,
2.2 Lottery Arbiter 6

lottery manger gives a numbered ticket/request to each master. The weight of the ticket
number is increased each time a specific master requests.

Figure 2.1: Lottery Manager [1]

Assuming a non-empty set of weights {w1 , w2 , ..., wn }, the probability of winning a


ticket can be calculated as in Eqn 2.2.

wi
pi = Pn (2.2)
j=1 wj

The manager draws the highest numbered ticket as a winner. The ticket count of the
granted master is reset on winning the lottery. The reset makes the current winner less
likely to be chosen on the next draw. In case of a tie, the manager may choose any master.
If there is only one master requesting, the manger will choose the trivial solution. As a
result of this pseudo-randomization, the masters get a fair share of bus time dictated by
the weight of the lottery ticket.
2.3 Matrix Arbiter 7

2.3 Matrix Arbiter

Matrix arbiters are designed to enforce last served master to have the lowest priority on
the shared resources. It keeps track of the priority in a square matrix form. The rows and
columns of the matrix represents the requestors. The ith row can be linked to requestor i
and j th column requestor j. Figure 2.2 shows the 4 requestors mapping in a 4 by 4 matrix.

Figure 2.2: Priority Matrix[2]

The rule of the matrix arbiter is if there is a 1 in ith row and j th column, requestor i
has priority over requestor j. As in Figure 2.3, if requestor 2 sends a request, the grant
will be issued to requestor 2. The elements in row 2 are set to zero. It forces requestor 2
to have the lowest priority. At the same time the elements in column 2 are set to 1. It
makes other requestors beat requestor 2 in the next iteration. Matrix arbiters are useful
when the number of inputs are small. If the number of requests increases, the structure of
the arbiter increases leading to larger area overhead[11].
2.3 Matrix Arbiter 8

Figure 2.3: Matrix Transition


Chapter 3

Weighted Round-Robin Arbiter

Round-robin arbitration has multiple flavors to fit the desired application. In some applica-
tions two-pick Round-robin arbiters are used instead of one pick arbiters[12]. However, the
final goal, starvation prevention and statistical fairness, is the same[13]. The algorithms
introduced in Chapter 2 give the grant to the master that has the higher priority. It means
a master has the ability to monopolize the bus for a long time. This causes bus starvation
to the masters with lower priorities. Weighted Round-robin arbiter design is based on the
algorithm that the scheduling of grants must go on in a Round-robin manner. This work
is based on a two-step approach. The arbiter monitors the requests and give them grants
in the next clock. In best case condition, the request at time ti will get serviced at time
ti+1 [14]. This scheduling algorithm makes sure each master gets its share of time slice in
a fair amount of time. A good analogy would be if there are 4 masters in x cycle arbiter,
each master will get a quantized time slice of x/4 cycles. However, in some applications,
one bus master may require more bus time than others. Figure 3.1 shows top level view of
Round-robin arbiter in a network packet switching system.
3.1 Weight Decoder 10

Figure 3.1: Packet Switching Architecture

This paper introduces another configurable variable called weight. The weight of each
master can be defined as the grant time slice that the master can configure in the arbiter.
If all the masters have the same amount of weight, each master will get an equal time
share of the pie. If master A requests 20 cycles and master B requests 10 cycles, master
A will get grant 2 times longer than master B. One disadvantage of letting the masters to
configure the weight is a master may configure a very large weight. To reduce this large
weight monopoly, another global configurable maximum allowed weight is added. A master
may request a very large weight value, but the arbiter will only grant up to the maximum
allowed weight if there are other masters waiting.

3.1 Weight Decoder

Weight decoder decodes one-hot grant to decode the correct weight of the granted master.
As shown in Figure 3.2, the weight of the masters are concatenated to form a weight bus.
As in Eqn 3.1, the width of the bus can be calculated by the width of a single weight and
the total number of masters in the arbiter.
3.1 Weight Decoder 11

Figure 3.2: Weight Bus Size

busW idth = weightW idth ∗ numOf M asters (3.1)

Weight decoder takes current grant as an one-hot input. The input grant is decoded
to produce an index for correct bit slice positions of the weight bus. Figure 3.3 shows
the flowchart to produce the correct index. For example, if the grant is b′ 0010, the index
output is 1. Index of 1 stands for the master no. 1. The weight of master 1 is decoded as
an output. If the grant is b′ 0100, index output is 2. The weight of master 2 is decoded as
an output.
3.2 Next Grant Precalculator 12

Figure 3.3: One-hot Index Flowchart

3.2 Next Grant Precalculator

Next Grant PReCalculator(NGPRC) calculates the next possible grants mask based on
current grant. By precalculating the next possible grants, NGPRC dictates the Round-
robin arbitration of the arbiter. As in Figure 3.4, if all 4 masters in the arbiter are
3.2 Next Grant Precalculator 13

requesting and current grant is master 1, next possible grant is restricted to be in the order
of master 2, master 3 and master 0. The arbiter cannot skip master 2 to grant master 3.
It would violate Round-robin scheme and it is not allowed. By giving next possible grant
priority to the Grant State-machine, it forces the grant to be in strict Round-robin order.

Figure 3.4: Next Grant PreCalculator

Figure 3.5 shows the calculation steps NGPRC takes to compute the next possible grant
priority. For example, if current grant is b′ 0010, rotate left gives b′ 0100. After inversion,
the bits become b′ 1011. After increment by 1, the next possible grant becomes b′ 1100. It
means the leftmost 2 bits are in line in priority.
3.3 Grant State Machine 14

Figure 3.5: NGPRC Calculation Steps

3.3 Grant State Machine

Grant state machine is the logic to calculate which master gets the grant and for how long
based on the weight. The grant logic is based on the requests and next grant priority
mask created by NGPRC. Figure 3.6 shows the state flow diagram of grant state machine.
“Grant Process” state masks requests using precalculated mask to grant the next requesting
master. After the grant is decided, it moves to “Get Weight” state to fetch the weight of
the grant from Weight Decoder. After that, it moves to “Count” state to count the clock
cycles until local counter reaches the desired weight.
3.3 Grant State Machine 15

Figure 3.6: Grant State Machine


Chapter 4

SystemVerilog Verification Design

As the sizes and complexity of electronic design increases, faster integration of design and
verification of complex systems become mandatory[15]. The beginning of a new feature
starts with architectural exploration and ends with functional verification. The studies
find that the verification of a design occupies the most amount of time in a project life-
cycle[16]. The time required to verify a design from the end of a design life-cycle can
be defined as a verification gap. As engineers reuse Intellectual Property (IP) cores, de-
sign engineers can produce complex features in short time. However, these new features
are still needed to be verified. As a result, the verification gap increases as the product
cycle rotates between debugging and verification. To reduce the gap, design engineers
and verification engineers have to come to an agreement of having a universal verification
process[17]. SystemVerilog language is introduced as a common language to design verifi-
cation environment as a Universal Verification Methodology (UVM). A unified verification
methodology is important because about 70% of the design cycle time is used to develop
verification environment[18]. The re-usability of the verification environment shortens the
verification gap. A general verification includes multiple layers that can be re-used with
17

minimal change to the design[19]. As in Figure 4.1:

• Test Layer : Different test cases with constraint random and/or direct stimulus.

• Scenario Layer : Generates random stimulus based on the test cases.

• Functional Layer : This layer predicts possible Device Under Test (DUT) outputs
(golden test vectors) based on the random inputs using a reference mode[20]. It may
also contain a scoreboard to keep track of the results.

• Command Layer : Command layer is a pin-level layer. On the input side, it receives
stimulus from functional layer and drives the DUT. DUT output is also monitored
to be compared with golden test vectors.

SystemVerilog is used to verify the proposed Round-robin arbiter. SystemVerilog verifica-


tion can be designed in an object oriented way to allow classes, inheritance, class routine
sharing (polymorphism). It has the ability to randomize inputs and set constraints on the
randomness. Assertions are used to check for undesired behavior. The functional con-
verge sampling bins can be obtained through the defined coverage points. Mailboxes and
event triggers can be used to control synchronization between the modules. One of the
main advantages of developing SystemVerilog environment is it allows engineers to reuse
the classes and modules for a different project. The proposed SystemVerilog environment
contains requestor, generator, agent, driver, monitor, checker and scoreboard. Figure 4.1
shows the top level view of proposed SystemVerilog test environment.
4.1 Requestor 18

Figure 4.1: SystemVerilog Environment

4.1 Requestor

Requestor class is designed to behave like a master that would request access to the shared
resource from the arbiter. Requestor class contains two members, request and weight. The
members are of the type “rand”. It allows the calling class to be able to randomize to
provide random stimuli to the DUT. Having random test cases is important because the
verification engineers might not be able to consider many combinations of test cases for
complex systems. However, randomization can produce test cases not applicable to DUT.
Adding constraints to the random variable makes the random stimuli applicable to the
target DUT verification. Verification engineers spend most of the time on iterating runs
by adding constraints and various random seeds. To achieve full coverage, some direct test
4.2 Generator 19

cases may be required to fully close the loop. Figure 4.2 shows the functional coverage
loop.

Figure 4.2: Function Coverage Loop [3]

4.2 Generator

Generator is a part of Scenario Layer. The purpose of the generator is to create different
test stimuli based on scenarios. For example, the verification of a TV remote have many test
scenarios. One of the test scenarios could be pressing mute button. A different test scenario
could be changing channels or adjust volumes. In case of Round-robin arbiter, random
requests/non-request could be simulated with different weights. The requestor class is
instantiated in generator. The generator class generates different requests by randomizing
the requestor class. Generator module can be used to generate different random stimuli
according to the different test case scenarios.
4.3 Agent 20

4.3 Agent

Agent is located in functional level. As in Figure 4.1, agent acts as a mediator between
Scenario Layer and Command Layer. At functional level, agent class is responsible to
receive stimuli and predict output of DUT according to that stimuli. To achieve that,
agent class usually has a functional model of Device Under Test. The input stimuli and
predicted output test vectors can be called “golden” test vectors. Engineers can analyze
the input test vector set to predict the expected output results.
In this verification environment, the agent class instantiates the generator class. The
stimuli generated by the generator are used to convert to golden test vectors by predicting
the expected outcome of the given stimuli. Each randomization contains a bit representing
request or no-request accompanied by the weight. The model checks for the bit and if the
bit is request bit, the weight value is recoded as the number of clock cycles the bit should
be granted. If the bit is no-request the the output is recorded as no request with zero
cycles. The test vectors are passed onto the driver module and expected golden vectors to
checker module.

4.4 Driver

The driver located in Command Layer is closest to hardware. Driver class connects the
input of DUT to the rest of the verification environment. It is responsible to drive signals
synchronously to DUT. It can contains functions such as reset conditions. The test vectors
from agent are driven to DUT by the driver in synchronous with system clock. In this
verification environment, request bits and weights are driven to DUT using DUT system
clock. Because driver controls the input of DUT, Monitor class described in the following
section needs to know when the driver finished driving a particular test vector. The
4.5 Monitor 21

synchronization between class modules is done using event triggering. After driver finished
sending a set of test vector to DUT, it raises an event for monitor class to catch. Monitor
class uses this event to know the respective DUT output. By having synchronization,
driver can insure that all the input test vectors are aligned correctly with the expected
golden test vectors.

4.5 Monitor

Similar to driver class, monitor class resides in Command Layer. Monitor class is connected
to the output of DUT to capture data from DUT output ports synchronously. The purpose
of monitor is to record DUT output for each input driven by driver. The recorded data
can be transferred to checker module to check for errors.
In this verification environment, monitor module starts counting once it sees a grant
signal of a request. The number of cycles or the amount of time a request is granted can be
determined by the counter value of the monitor. For example, if a requestor 1 is granted
for 5 clock cycles, monitor will get a count of 5 for requestor 1. In other words, monitor
collects the grants and their respective granted cycles. The collected data is sent to the
check to be matched with the golden test vectors.

4.6 Checker

Like Agent class, Checker class is located in Functional Layer. Checker class is responsible
to match the output of DUT collected by monitor and the golden test vectors predicted by
reference model. In this verification environment, checker class receives grants and grant
time (cycles) from monitor module. It also receives the expected output of golden test
4.7 Scoreboard 22

vectors. For each test data set, checker verifies DUT output against golden test vectors.
It also records the verification statistics in scoreboard.

4.7 Scoreboard

As the name stands, Scoreboard module contains the statistics of current verification.
Checker module calls the “record” member function of scoreboard after each test vector.
The function records which requestor (master) is granted by updating member variables.
Using the recorded data, statistical analysis can be performed.

4.8 Determinism

If a bug were found during the verification process, it is important for the design and
verification engineers to be able to reproduce easily. Knowing the sets of test vectors
caused the failure is crucial for debugging purposes. Therefore, when the requestor module
is instantiated in Generator module, the seed of the requestor’s random variables can be
set. Each “randomize” function call is based on a different seed. If a failure occurs, the
seed of the failure test vectors can be extracted for the design engineers to debug. It
allows verification engineers to reproduce the failing inputs easily without restarting the
whole verification process. This approach of seeding makes the randomization process to
be deterministic every iteration in every run.
Chapter 5

Tests and Results

This section discusses the simulation results of the arbiter, as well as the area and power
overhead of the top level design.

5.1 Simulation

5.1.1 Weight Decoder

Figure 5.1: Weight Decoder

Figure 5.1 shows the simulation of weight decoder. Input dataInBus contains the weights
of the channels preconfigured. Input selOneHot port/grant the input used to decode the
weight of current grant. The decoded weight is outputted to the dataOut port.
5.2 SystemVerilog Verification Results 24

5.1.2 Next Grant PreCalculator

Figure 5.2: Next Grant PreCalculator

Figure 5.2 shows the simulation waveform of Next Grant PreCalculator. Based on the input
request and grant, next grant mask is created to dictate Round-robin order to restrict the
grant order.

5.1.3 Round-Robin Top Level/Grant State Machine

Figure 5.3: Top Level Simulation

The Figure 5.3 shows the simulation top level Round-Robin Arbiter. Grant is serviced
based on the requests and precalculated mask from NGPRC. The grant is given the access
time for the number of weight cycles before servicing the next request.

5.2 SystemVerilog Verification Results

5.2.1 Scoreboard scores

Table 5.1 shows the results of SystemVerilog verification of 20,000 iterations. As seen in
the table, the hit score distribution is fairly uniform since the randomization of test vector
generation is based on uniform probability distribution.
5.3 System Overhead 25

Table 5.1: SystemVerilog Verification Hit Scores

Score
Channel 0 1021
Channel 1 972
Channel 2 1036
Channel 3 980
Channel 4 1048
Channel 5 995
Channel 6 1009
Channel 7 971

5.3 System Overhead

5.3.1 Area Overhead

The arbiter is synthesized using a TSMC 65 nm technology library and Synopsis Design
Compiler using a two step process. The first step, RTL synthesis, performs logic synthesis
and produces what is called a pre-scan netlist. In the second step, test synthesis, Design
For Test (DFT) structures for full scan testing are added to the design and optimized
producing what is called a post-scan netlist. The top level design is targeted at 8 channels
to be able to arbitrate 8 different requestors. Table 5.2 shows the pre-scan and post-scan
area overhead for Weight Decoder, Next Grant PreCalculator and Grant Statemachine.

5.3.2 Power Overhead

Similarly, Table 5.3 shows power overhead for Weight Decoder, Next Grant PreCalculator
and Grant state machine.
5.3 System Overhead 26

Table 5.2: Area Overhead

Module Pre-Scan
Combinational Non- Percent Total (µm2)
(µm2) Combinational Total (%)
(µm2)
Weight Decoder 612.0576 0.0000 13.4 612.0576
(MUX)
Next Grant 755.0928 691.8912 31.8 1446.9840
PreCalculator
(NGPRC)
Grant 1167.5664 1327.2336 54.8 2494.8000
Statemachine
(Grant)
Top Level Arbiter 2534.7168 2019.1248 100 4553.8416
Module (8
Channels)
Post-Scan
Weight Decoder 612.0576 0.0000 12.4 612.0576
(MUX)
Next Grant 755.0928 828.2736 32.0 1583.3664
PreCalculator
(NGPRC)
Grant 1167.5664 1580.0401 55.6 2747.6065
Statemachine
(Grant)
Top Level Arbiter 2534.7168 2408.3137 100.0 4943.0305
Module (8
Channels)
5.3 System Overhead

Table 5.3: Power Overhead

Netlist
Group Internal Switching Leakage Total Percentage
Type
Register 9.9823e-02 mW 4.3251e-03 mW 9.9996 nW 0.1042 mW 76.50 %
Pre-Scan
3.1997e-02
Netlist Combinational 1.1323e-02 mW 2.0664e-02 mW 9.8877 nW 23.50 %
mW
Total 0.1111 mW 2.4989e-02 mW 19.8873 nW 0.1362 mW 100 %
Register 0.1240 mW 9.2250e-03 mW 11.8287 nW 0.1332 mW 74.45 %
Post-Scan
4.5710e-02
Netlist Combinational 1.7618e-02 mW 2.8082e-02 mW 9.8877 nW 25.55 %
mW
Total 0.1416 mW 3.7307e-02 mW 21.7164 nW 0.1789 mW 100 %
27
Chapter 6

Conclusions

This work discussed the design and verification of Round-Robin Arbitration. As the num-
ber of masters requires access the shared resources increases, a good arbitration system
becomes essential. This work focused on the fairness metric to measure the performance
of an arbiter. However, it is important to not overlook the area overhead and power con-
sumption. A complex system may have good fairness at the trade-off of large overhead.
Therefore, the design preference is based on the application of the arbiter. Round-robin ar-
biter is chosen because of its fairness in granting access. Bus grant time quantization allows
the requestors to be able to predict the maximum amount of time to get grant. However,
in some applications, one requestor might require to have the grant twice as long. This
work introduced the weight or the number of clock cycle that the requestor can configure
during synthesis. This makes the fairness adjustable (more fair or less fair). At the same
time, increasing or decreasing the weights allows the time quantization adjustable.
SystemVerilog is used as a verification environment for the design. By having a verifi-
cation environment, engineers can have a higher confidence on the release of the product.
Code maintenance is easier for each time the design changes due to bugs or feature intro-
6.1 Future Work 29

duction as the verification can filter out issues before reaching to the customers. This work
discussed that design process from the aspect of customer requirements and applications.
To summarize, although fairness is used as a performance measurement, fairness is
only good when a particular application requires it. This Round-Robin Arbiter design
is customized to be more fair or less fair. The design trade-off between fairness and/or
overhead remains at the process of the intended design application.

6.1 Future Work

Since the arbiter are application specific, for future work, this implementation of Round-
robin arbiter can be modified to suit the intended usage. One of the applications of
Round-robin arbiter is system-on-chip shared memory. In this application, two independent
Round-robin arbiters are used, one for address and one for data. For read access, the two
arbiters can operate independently[21]. However, for write back operations, both the data
and address needs to go together[22]. It might be beneficial to implement a modified
version that is aware of the condition when address or data arbiter needs to freeze in order
to write back.
Another applications is communication arbiter for Network-On-Chip (NOC), where
communication between IP cores are usually non-uniform or hot-spot in traffic[22, 23].
The arbiter in this work only allow a fixed time slice preconfigured. It would be beneficial
to implement logic to detect the load of the inputs and adjust priority dynamically. By
adjusting priority or grant time based on the traffic would make sure that busy master/re-
questor traffic is well balanced and not starved.
References

[1] K. Warathe, D. Padole, and P. Bajaj, “A Design Approach to AMBA (Advanced


Microcontroller Bus Architecture) Bus Architecture with Dynamic Lottery Arbiter,”
in 2009 Annual IEEE India Conference, Dec 2009, pp. 1–4.

[2] Z. Fu and X. Ling, “The design and implementation of arbiters for Network-on-chips,”
in 2010 2nd International Conference on Industrial and Information Systems, vol. 1,
July 2010, pp. 292–295.

[3] C. Spear, SystemVerilog for Verification: A Guide to Learning the Testbench Language
Features. New York NY: Springer, 2006.

[4] Y. Li, N. Zeng, W. N. N. Hung, and X. Song, “Enhanced symbolic simulation of


a round-robin arbiter,” in 2011 IEEE 29th International Conference on Computer
Design (ICCD), Oct 2011, pp. 102–107.

[5] S. Q. Zheng and M. Yang, “Algorithm-Hardware Codesign of Fast Parallel Round-


Robin Arbiters,” IEEE Transactions on Parallel and Distributed Systems, vol. 18,
no. 1, pp. 84–95, Jan 2007.

[6] M. Abdelrasoul, M. Ragab, and V. Goulart, “Impact of Round Robin Arbiters on


References 31

router’s performance for NoCs on FPGAs,” in 2013 IEEE International Conference


on Circuits and Systems (ICCAS), Sept 2013, pp. 59–64.

[7] Y. Yang, R. Wu, L. Zhang, and D. Zhou, “An Asynchronous Adaptive Priority Round-
Robin Arbiter Based on Four-Phase Dual-rail Protocol,” Chinese Journal of Electron-
ics, vol. 24, no. 1, pp. 1–7, 2015.

[8] K. A. Helal, S. Attia, T. Ismail, and H. Mostafa, “Priority-select arbiter: An efficient


round-robin arbiter,” in 2015 IEEE 13th International New Circuits and Systems
Conference (NEWCAS), June 2015, pp. 1–4.

[9] R. Kamal and J. M. M. Arostegui, “RTL implementation and analysis of fixed pri-
ority, round robin, and matrix arbiters for the NoC’s routers,” in 2016 International
Conference on Computing, Communication and Automation (ICCCA), April 2016,
pp. 1454–1459.

[10] E. S. Shin, V. J. Mooney, and G. F. Riley, “Round-robin Arbiter Design and Gener-
ation,” in 15th International Symposium on System Synthesis, 2002., Oct 2002, pp.
243–248.

[11] M. Oveis-Gharan and G. N. Khan, “Index-Based Round-Robin Arbiter for NoC


Routers,” in 2015 IEEE Computer Society Annual Symposium on VLSI, July 2015,
pp. 62–67.

[12] H. F. Ugurdag, F. Temizkan, O. Baskirt, and B. Yuce, “Fast two-pick n2n round-robin
arbiter circuit,” Electronics Letters, vol. 48, no. 13, pp. 759–760, June 2012.

[13] K. C. Lee, “A variable round-robin arbiter for high speed buses and statistical mul-
tiplexers,” in [1991 Proceedings] Tenth Annual International Phoenix Conference on
Computers and Communications, Mar 1991, pp. 23–29.
References 32

[14] K. Yoghigoe, K. J. Christensen, and A. Roginsky, “Design of a high-speed overlapped


round robin (ORR) arbiter,” in Local Computer Networks, 2003. LCN ’03. Proceed-
ings. 28th Annual IEEE International Conference on Local Computer Networks, Oct
2003, pp. 638–639.

[15] S. Marconi, E. Conti, J. Christiansen, and P. Placidi, “Reusable SystemVerilog-UVM


design framework with constrained stimuli modeling for High Energy Physics applica-
tions,” in 2015 IEEE International Symposium on Systems Engineering (ISSE), Sept
2015, pp. 391–397.

[16] D. Rich, “The unique challenges of debugging design and verification code jointly in
SystemVerilog,” in Proceedings of the 2013 Forum on specification and Design Lan-
guages (FDL), Sept 2013, pp. 1–7.

[17] M. Rashid, M. W. Anwar, and F. Azam, “Expressing embedded systems verification


aspects at higher abstraction level - SystemVerilog in Object Constraint Language
(SVOCL),” in 2016 Annual IEEE Systems Conference (SysCon), April 2016, pp. 1–7.

[18] P. Gurha and R. R. Khandelwal, “SystemVerilog Assertion Based Verification of


AMBA-AHB,” in 2016 International Conference on Micro-Electronics and Telecom-
munication Engineering (ICMETE), Sept 2016, pp. 641–645.

[19] R. Sethulekshmi, S. Jazir, R. A. Rahiman, R. Karthik, S. Abdulla M, and


S. Sree Swathy, “Verification of a RISC processor IP core using SystemVerilog,” in
2016 International Conference on Wireless Communications, Signal Processing and
Networking (WiSPNET), March 2016, pp. 1490–1493.

[20] Y. Zhu, T. Li, J. Guo, H. Zhou, and F. Fu, “A novel low-cost interface design for Sys-
References 33

temC and SystemVerilog Co-simulation,” in 2015 IEEE 11th International Conference


on ASIC (ASICON), Nov 2015, pp. 1–4.

[21] R. Bhaktavatchalu, B. S. Rekha, G. A. Divya, and V. U. S. Jyothi, “Design of AXI bus


interface modules on FPGA,” in 2016 International Conference on Advanced Commu-
nication Control and Computing Technologies (ICACCCT), May 2016, pp. 141–146.

[22] J. Reed and N. Manjikian, “A dual round-robin arbiter for split-transaction buses
in system-on-chip implementations,” in Canadian Conference on Electrical and Com-
puter Engineering 2004 (IEEE Cat. No.04CH37513), vol. 2, May 2004, pp. 835–840
Vol.2.

[23] A. A. Khan, R. N. Mir, and N. ud din, “Buffer aware arbiter design to achieve improved
QoS for NoC,” in TENCON 2017 - 2017 IEEE Region 10 Conference, Nov 2017, pp.
2494–2499.

[24] J. Bromley, “If SystemVerilog is so good, why do we need the UVM? Sharing respon-
sibilities between libraries and the core language,” in Proceedings of the 2013 Forum
on specification and Design Languages (FDL), Sept 2013, pp. 1–7.

[25] J. Wang, Y. Li, Q. Peng, and T. Tan, “A dynamic priority arbiter for Network-on-
Chip,” in 2009 IEEE International Symposium on Industrial Embedded Systems, July
2009, pp. 253–256.
Appendix I

Arbiter Source Code


Listing I.1: Weight Decoder Module

// MUX module
// This module s e l e c t s one o f t h e i n p u t s a c c o r d i n g t o t h e i n p u t s e l e c t
signal
// C o m b i n a t i o n a l L o g i c
// I n p u t : selOneHot − s i g n a l ONE HOT STYLE
// : daataInBus − i n p u t d a t a bus f o r a l l c h a n n e l s c o n c a t from
ch0 t o
// chN
// Output : dataOut − o u t p u t d a t a a c c o r d i n g t o s e l e c t s i g n a l
//

module MUX
#(
parameter WIDTH = 3 2 , // w i d t h o f each c h a n n e l
parameter CHANNELS = 8 // number o f c h a n n e l s
)
(
reset ,
clk ,
scan_in0 ,
scan_in1 ,
scan_in2 ,
scan_in3 ,
scan_in4 ,
scan_enable ,
I-2

test_mode ,
scan_out0 ,
scan_out1 ,
scan_out2 ,
scan_out3 ,
scan_out4 ,
selOneHot , // one h o t s e l e c t i n p u t
dataInBus , // i n p u t bus
dataOut // o u t p u t d a t a
);

input
reset , // system r e s e t
clk ; // system c l o c k

input
scan_in0 , // test scan mode data input
scan_in1 , // test scan mode data input
scan_in2 , // test scan mode data input
scan_in3 , // test scan mode data input
scan_in4 , // test scan mode data input
scan_enable , // test scan mode enable
test_mode ; // test mode

output
scan_out0 , // test scan mode data output
scan_out1 , // test scan mode data output
scan_out2 , // test scan mode data output
scan_out3 , // test scan mode data output
scan_out4 ; // test scan mode data output

i n p u t [ (CHANNELS−1) : 0 ] selOneHot ; // one h o t s e l e c t i n p u t


i n p u t [ (CHANNELS∗WIDTH)−1 : 0 ] dataInBus ; // i n p u t d a t a bus

output r e g
[ (WIDTH−1) : 0 ] dataOut ; // o u t p u t d a t a a f t e r s e l e c t

// r e g [ (CHANNELS∗WIDTH)−1 : 0 ] tempData ;

// g e n e r a t e v a r i a b l e
genvar gv ;
I-3

//−−− COMBINATIONAL SECTION −−−//

// temporary a r r a y t o h o l d i n p u t c h a n n e l s
w i r e [ (WIDTH−1) : 0 ] i n p u t A r r a y [ 0 : (CHANNELS−1) ] ;

generate
// g e n e r a t e s t a t e m e n t t o a s s i g n i n p u t c h a n n e l s t o temp a r r a y
f o r ( gv = 0 ; gv < CHANNELS; gv = gv+1) b e g i n : a r r a y A s s i g n m e n t s

a s s i g n i n p u t A r r a y [ gv ] = dataInBus [ ( ( gv+1)∗WIDTH )−1 : ( gv ∗


WIDTH) ] ;

end // a r r a y A s s i g n m e n t s
endgenerate

// f u n c t i o n t o c o n v e r t one h o t t o d e c i m a l
function i n t e g e r decimal ;
i n p u t [CHANNELS−1 : 0 ] oneHotInput ;
integer i ;
f o r ( i = 0 ; i <CHANNELS; i = i +1)
i f ( oneHotInput [ i ] )
decimal = i ;

endfunction

// s e l e c t t h e o u t p u t a c c o r d i n g t o i n p u t oneHot
always@ ∗
begin
dataOut = i n p u t A r r a y [ d e c i m a l ( selOneHot ) ] ;
end // end a l w a y s

endmodule // MUX
I-4

Listing I.2: Weight Decoder Test Module

module t e s t ;
l o c a l p a r a m WIDTH = 3 2 ;
l o c a l p a r a m CHANNELS = 8 ;

// c l o c k p e r i o d
l o c a l p a r a m CLOCK_PERIOD = 2 0 ; // 20 ns (50Mhz)

w i r e scan_out0 , scan_out1 , scan_out2 , scan_out3 , scan_out4 ;


reg clk , r e s e t ;
r e g scan_in0 , scan_in1 , scan_in2 , scan_in3 , scan_in4 , scan_enable ,
test_mode ;

// i n p u t s
r e g [ (CHANNELS−1) : 0 ] t e s t _ s e l O n e H o t ;
r e g [ (CHANNELS∗WIDTH)−1 : 0 ] t e s t _ d a t a I n B u s ;

// o u t p u t
w i r e [ (WIDTH−1) : 0 ] test_dataOut ;

// f l o w control flags
integer testDoneFlag = 0 ;
integer i = 1;
integer j = 0;
integer k = 0;
integer waveCounter = 1 ;

// temp r e g / v a r i a b l e s
r e g [ (WIDTH−1) : 0 ] tempDataIn ;
r e g [ (WIDTH−1) : 0 ] dataArray [ (CHANNELS−1) : 0 ] ; // a r r a y t o c h e c k
output

MUX top (
. reset ( reset ) ,
. clk ( clk ) ,
. scan_in0 ( scan_in0 ) ,
. scan_in1 ( scan_in1 ) ,
. scan_in2 ( scan_in2 ) ,
. scan_in3 ( scan_in3 ) ,
. scan_in4 ( scan_in4 ) ,
I-5

. scan_enable ( scan_enable ) ,
. test_mode ( test_mode ) ,
. scan_out0 ( scan_out0 ) ,
. scan_out1 ( scan_out1 ) ,
. scan_out2 ( scan_out2 ) ,
. scan_out3 ( scan_out3 ) ,
. scan_out4 ( scan_out4 ) ,
. selOneHot ( t e s t _ s e l O n e H o t ) ,
. dataInBus ( t e s t _ d a t a I n B u s ) ,
. dataOut ( test_dataOut )
);

initial
begin
$ t i m e f o r m a t ( −9 ,2 , " ns " , 1 6 ) ;
` i f d e f SDFSCAN
$ s d f _ a n n o t a t e ( " s d f /ADDC_tsmc18_scan . s d f " , t e s t . top ) ;
`endif
c l k = 1 ' b0 ;
r e s e t = 1 ' b0 ;
scan_in0 = 1 ' b0 ;
scan_in1 = 1 ' b0 ;
scan_in2 = 1 ' b0 ;
scan_in3 = 1 ' b0 ;
scan_in4 = 1 ' b0 ;
scan_enable = 1 ' b0 ;
test_mode = 1 ' b0 ;

// i n i t i a l i z e i n p u t t o 1
test_ s e l O n e H o t = 1 ;

// s e t t h e v e r y f i r s t w e i g h t t o 2 ( c h a n n e l 0)
test_dataInBus = 2 ;
tempDataIn = 2 ;
dataArray [ 0 ] = 2 ;

// i n p u t w e i g h t d a t a bus g e n e r a t i o n
f o r ( j = 1 ; j < CHANNELS; j = j +1)
begin
// m a n i p u l a t e t e s t d a t a f o r each c h a n n e l ( i n c r e m e n t by 2 i n
t h i s case )
tempDataIn = tempDataIn + 2 ;
I-6

// s e t w e i g h t d a t a bus by s h i f t i n g and b i t w i s e or
t e s t _ d a t a I n B u s = t e s t _ d a t a I n B u s | ( tempDataIn << WIDTH∗ j ) ;

// s a v e d a t a t o o u t p u t c h e c k e r a r r a y as w e l l
dataArray [ j ] = tempDataIn ;

end

while ( ! testDoneFlag )
begin
@( p o s e d g e c l k )
begin
// a s s i g n i t o s e l i n p u t as t e s t v e c t o r
test_selOneHot = i ;

// i =1 w i l l be s h i f t e d by 1 from b i t 0 t o b i t (WIDTH−1)
i = i << 1 ;

// r e s e t i f we o v e r f l o w
i f ( t e s t _ s e l O n e H o t == 0 )
i = 1;
end

end

end

// c h e c k o u t p u t i n p a r a l l e l on n e g a t i v e e d g e
always @( negedge c l k )
begin
f o r ( k = 0 ; k < CHANNELS; k = k+1)
begin
// make s u r e i n p u t i s v a l i d ( one h o t )
i f ( t e s t _ s e l O n e H o t == 1 << k )
// c h e c k i f DUT o u t p u t matches e x p e c t e d o u t p u t
i f ( test_dataOut !== dataArray [ k ] )
begin
// d i s p l a y u s e f u l i n f o r m a t i o n i f t h e o u t p u t s don ' t
match
$ d i s p l a y ( " Wrong␣ output ␣ a t ␣%0t " , $time ) ;
I-7

$ d i s p l a y ( " Expected ␣%H, ␣ Actual ␣%H" , dataArray [ k ] ,


test_dataOut ) ;

// s t o p i f we s e e e r r o r
// $ f i n i s h ;
end

end

// c ou n t waves
waveCounter = waveCounter + 1 ;

// s t o p i f we l o o p e d t h r o u g h a l l c h a n n e l v a l u e s (∗2 t o s e e some
extra
// l e n g t h )
i f ( waveCounter >= CHANNELS∗ 2 )
$finish ;
end

// c l o c k g e n e r a t i o n
always #(CLOCK_PERIOD/ 2 )
clk = ~clk ;

endmodule
I-8

Listing I.3: Next Grant Precalculator Module

// NGPRC module
// Next Grant P Re Ca l cu la t e
//
//
// This module p r e c a l c u l a t e t h e mask f o r t h e Grant P r o c e s s
// The mask i s s h f t e d l e f t t o d i c t a t e round r o b i n manner
// I n p u t : r e q u e s t , g r a n t
// Output : nextGrant mask
//
module NGPRC
#(
parameter CHANNELS = 8 // t o t a l number o f r e q u e s t o r s
)
(
reset ,
clk ,
scan_in0 ,
scan_in1 ,
scan_in2 ,
scan_in3 ,
scan_in4 ,
scan_enable ,
test_mode ,
scan_out0 ,
scan_out1 ,
scan_out2 ,
scan_out3 ,
scan_out4 ,

// i n p u t s
request , // r e q u e s t i n p u t
grant , // g r a n t i n p u t

// o u t p u t s
nextGrant // n e x t g r a n t o u t p u t

);

input
reset , // system r e s e t
clk ; // system c l o c k
I-9

input
scan_in0 , // test scan mode data input
scan_in1 , // test scan mode data input
scan_in2 , // test scan mode data input
scan_in3 , // test scan mode data input
scan_in4 , // test scan mode data input
scan_enable , // test scan mode enable
test_mode ; // test mode

output
scan_out0 , // test scan mode data output
scan_out1 , // test scan mode data output
scan_out2 , // test scan mode data output
scan_out3 , // test scan mode data output
scan_out4 ; // test scan mode data output

i n p u t [ (CHANNELS−1) : 0 ] r e q u e s t ;
i n p u t [ ( CHANNELS−1) : 0 ] g r a n t ;

output r e g [ ( CHANNELS−1) : 0 ] nextGrant ;

r e g [ (CHANNELS−1) : 0 ] p r i o r i t y M a s k ;

//−−− I n t e r n a l C o n s t a n t s −−−//
l o c a l p a r a m SIZE = 2 ;

// STATES
r e g [ ( SIZE−1) : 0 ] s t a t e ;

l o c a l p a r a m RESET = ' b01 ; // 3 ' b001


l o c a l p a r a m NEXT_GRANT = ' b10 ; // 3 ' b010

//−−− Code S t a r t s −−//

// a l w a y s b l o c k f o r s t a t e t r a n s i t i o n
always@ ( p o s e d g e c l k , p o s e d g e r e s e t )
begin : preCalStateTransition

i f ( r e s e t == 1 ' b1 )
begin
I-10

s t a t e = RESET;
end
else
// s t a t e t r a n s i t i o n
case ( state )
// c h e c k i f we a r e o u t o f r e s e t
RESET :
begin
// t r a n s i t i o n r i g h t away once NOT i n r e s e t
s t a t e = NEXT_GRANT;

end

NEXT_GRANT :
begin
// go b a c k t o r e s e t i f t h e r e i s r e s e t
state = state ;

end

default :
begin
// s t a y i n t h e same s t a t e
s t a t e = RESET;
end

endcase

end

// o u t p u t l o g i c
always @( p o s e d g e c l k , p o s e d g e r e s e t )
b e g i n : preCalOutputLogic
i f ( r e s e t == 1 ' b1 )
begin

nextGrant = 0 ;
priorityMask = 0;
end
else
I-11

case ( state )
// r e s e t s i g n a l s i n r e s e t s t a t e
RESET :
begin

nextGrant = 0 ;
priorityMask = ~0;

end

// s e t n e x t g r a n t and p r i o r i t y M a s k
// Handle wrap around c a s e
NEXT_GRANT :
begin

// c a l c u l a t e p r i o r i t y M a s k
// R o t a t e l e f t , i n v e r t and add 1
p r i o r i t y M a s k = ~{ g r a n t [CHANNELS−2 : 0 ] , g r a n t [CHANNELS−1]}
+ 1;

// i f g r a n t somehow becomes ze r o , s e t p r i o r i t y M a s k t o a l l
1
i f ( p r i o r i t y M a s k == 0 )
priorityMask = ~0;
else
priorityMask = priorityMask ;

// c a l c u l a t e nextGrant
nextGrant = r e q u e s t & p r i o r i t y M a s k ;
// nextGrant = p r i o r i t y M a s k ;

// i f we s e e a r e q u e s t b u t nextGrant i s z e r o
// i t means we wrap around
i f ( ( nextGrant == 0 ) && ( r e q u e s t != 0 ) )
nextGrant = request ;

end

// i f s t a t e m a c h i n e n e v e r g o e s o u t o f wack
// we s h o u l d NOT r e a c h t o t h i s c a s e
default :
begin
// k e e p a l l t h e s i g n a l s t h e same
I-12

priorityMask = priorityMask ;
nextGrant = nextGrant ;

end

endcase
end

endmodule //NGPRC
I-13

Listing I.4: Next Grant Precalculator Test Module

module t e s t ;
l o c a l p a r a m WIDTH = 3 2 ;
l o c a l p a r a m CHANNELS = 8 ;

// c l o c k p e r i o d
l o c a l p a r a m CLOCK_PERIOD = 1 0 0 ; // 20 ns (50Mhz)

w i r e scan_out0 , scan_out1 , scan_out2 , scan_out3 , scan_out4 ;


reg clk , r e s e t ;
r e g scan_in0 , scan_in1 , scan_in2 , scan_in3 , scan_in4 , scan_enable ,
test_mode ;

// i n p u t s
r e g [ (CHANNELS−1) : 0 ] t e s t _ r e q u e s t ;
r e g [ (CHANNELS−1) : 0 ] t e s t _ g r a n t ;

// f l o w c o n t r o l
r e g [ (CHANNELS−1) : 0 ] expectedNextGrant ;
reg sticky ;

// o u t p u t
w i r e [ (CHANNELS−1) : 0 ] t es t_n e x tG r an t ;
w i r e [ 4 : 0 ] test_debugPreCal ;

NGPRC top (
. reset ( reset ) ,
. clk ( clk ) ,
. scan_in0 ( scan_in0 ) ,
. scan_in1 ( scan_in1 ) ,
. scan_in2 ( scan_in2 ) ,
. scan_in3 ( scan_in3 ) ,
. scan_in4 ( scan_in4 ) ,
. scan_enable ( scan_enable ) ,
. test_mode ( test_mode ) ,
. scan_out0 ( scan_out0 ) ,
. scan_out1 ( scan_out1 ) ,
I-14

. scan_out2 ( scan_out2 ) ,
. scan_out3 ( scan_out3 ) ,
. scan_out4 ( scan_out4 ) ,
// i n p u t
. request ( test_request ) ,
. grant ( test_grant ) ,

// o u t p u t
. nextGrant ( t e s t_ n e xt G ra n t )
// . debugPreCal ( t e s t _ d e b u g P r e C a l )
);

initial
begin
$ t i m e f o r m a t ( −9 ,2 , " ns " , 1 6 ) ;
` i f d e f SDFSCAN
$ s d f _ a n n o t a t e ( " s d f /ADDC_tsmc18_scan . s d f " , t e s t . top ) ;
`endif
c l k = 1 ' b0 ;
r e s e t = 1 ' b1 ;
scan_in0 = 1 ' b0 ;
scan_in1 = 1 ' b0 ;
scan_in2 = 1 ' b0 ;
scan_in3 = 1 ' b0 ;
scan_in4 = 1 ' b0 ;
scan_enable = 1 ' b0 ;
test_mode = 1 ' b0 ;

sticky = 0;
test_request = 0;
test_grant = 0;
// r e l e a s e r e s e t
@( p o s e d g e c l k ) ;
r e s e t = 1 ' b0 ;

// t e s t c a s e 1
// r e q u e s t = 0000_000
// g r a n t = don ' t c a r e
// nextGrant = 0000 _0000
@( p o s e d g e c l k ) ;
test_request = 0;
test_grant = 0;
I-15

expectedNextGrant = 0 ;
$ d i s p l a y ( "−−−−−Test ␣ c a s e ␣1−−−−−" ) ;
$ d i s p l a y ( " Request ␣=␣%b " , t e s t _ r e q u e s t ) ;
$ d i s p l a y ( " g r a n t ␣=␣%b " , t e s t _ g r a n t ) ;
@( negedge c l k ) ;
i f ( tes t _ ne x tG r a nt != expectedNextGrant )
begin
sticky = 1;
$ d i s p l a y ( " Expected ␣ next ␣ g r a n t ␣=␣%b , ␣ Actual ␣=␣%b " ,
expectedNextGrant , t es t _n e x tG r an t ) ;
end
else
$ d i s p l a y ( " next ␣ g r a n t ␣=␣%b " , t es t _n e x tG r an t ) ;

// t e s t c a s e 2
// r e q u e s t = 1111 _1111
// g r a n t = 0001
// nextGrant = 1111 _1110
@( p o s e d g e c l k ) ;
t e s t _ r e q u e s t = 8 'hFF ;
test_grant = 1;
expectedNextGrant = 8 ' b1111_1110 ;
$ d i s p l a y ( "−−−−−Test ␣ c a s e ␣2−−−−−" ) ;
$ d i s p l a y ( " Request ␣=␣%b " , t e s t _ r e q u e s t ) ;
$ d i s p l a y ( " g r a n t ␣=␣%b " , t e s t _ g r a n t ) ;
@( negedge c l k ) ;
i f ( tes t _ ne x tG r a nt != expectedNextGrant )
begin
sticky = 1;
$ d i s p l a y ( " Expected ␣ next ␣ g r a n t ␣=␣%b , ␣ Actual ␣=␣%b " ,
expectedNextGrant , t es t _n e x tG r an t ) ;
end
else
$ d i s p l a y ( " next ␣ g r a n t ␣=␣%b " , t es t _n e x tG r an t ) ;

// t e s t c a s e 3
// r e q u e s t = 1111 _1111
// g r a n t = 0010
// nextGrant = 1111 _1100
@( p o s e d g e c l k ) ;
I-16

t e s t _ r e q u e s t = 8 'hFF ;
t e s t _ g r a n t = 8 ' b0000_0010 ;
expectedNextGrant = 8 ' b1111_1100 ;
$ d i s p l a y ( "−−−−−Test ␣ c a s e ␣3−−−−−" ) ;
$ d i s p l a y ( " Request ␣=␣%b " , t e s t _ r e q u e s t ) ;
$ d i s p l a y ( " g r a n t ␣=␣%b " , t e s t _ g r a n t ) ;
@( negedge c l k ) ;
i f ( tes t _ ne x tG r a nt != expectedNextGrant )
begin
sticky = 1;
$ d i s p l a y ( " Expected ␣ next ␣ g r a n t ␣=␣%b , ␣ Actual ␣=␣%b " ,
expectedNextGrant , t es t _n e x tG r an t ) ;
end
else
$ d i s p l a y ( " next ␣ g r a n t ␣=␣%b " , t es t _n e x tG r an t ) ;

// t e s t c a s e 4
// r e q u e s t = 1111 _1111
// g r a n t = 0000 _0100
// nextGrant = 1111 _1000
@( p o s e d g e c l k ) ;
t e s t _ r e q u e s t = 8 'hFF ;
t e s t _ g r a n t = 8 ' b0000_0100 ;
expectedNextGrant = 8 ' b1111_1000 ;
$ d i s p l a y ( "−−−−−Test ␣ c a s e ␣4−−−−−" ) ;
$ d i s p l a y ( " Request ␣=␣%b " , t e s t _ r e q u e s t ) ;
$ d i s p l a y ( " g r a n t ␣=␣%b " , t e s t _ g r a n t ) ;
@( negedge c l k ) ;
i f ( tes t _ ne x tG r a nt != expectedNextGrant )
begin
sticky = 1;
$ d i s p l a y ( " Expected ␣ next ␣ g r a n t ␣=␣%b , ␣ Actual ␣=␣%b " ,
expectedNextGrant , t es t _n e x tG r an t ) ;
end
else
$ d i s p l a y ( " next ␣ g r a n t ␣=␣%b " , t es t _n e x tG r an t ) ;

// t e s t c a s e 5
// r e q u e s t = 1111 _1111
// g r a n t = 1000 _0000
// nextGrant = 1111 _1111
@( p o s e d g e c l k ) ;
I-17

t e s t _ r e q u e s t = 8 'hFF ;
t e s t _ g r a n t = 8 ' b1000_0000 ;
expectedNextGrant = 8 ' b1111_1111 ;
$ d i s p l a y ( "−−−−−Test ␣ c a s e ␣5−−−−−" ) ;
$ d i s p l a y ( " Request ␣=␣%b " , t e s t _ r e q u e s t ) ;
$ d i s p l a y ( " g r a n t ␣=␣%b " , t e s t _ g r a n t ) ;
@( negedge c l k ) ;
i f ( tes t _ ne x tG r a nt != expectedNextGrant )
begin
sticky = 1;
$ d i s p l a y ( " Expected ␣ next ␣ g r a n t ␣=␣%b , ␣ Actual ␣=␣%b " ,
expectedNextGrant , t es t _n e x tG r an t ) ;
end
else
$ d i s p l a y ( " next ␣ g r a n t ␣=␣%b " , t es t _n e x tG r an t ) ;

// t e s t c a s e 6
// r e q u e s t = 0000 _0000
// g r a n t = don ' t c a r e
// nextGrant = 0000 _0000
@( p o s e d g e c l k ) ;
t e s t _ r e q u e s t = 8 ' h00 ;
t e s t _ g r a n t = 8 ' b1 ;
expectedNextGrant = 8 ' b0 ;
$ d i s p l a y ( "−−−−−Test ␣ c a s e ␣6−−−−" ) ;
$ d i s p l a y ( " Request ␣=␣%b " , t e s t _ r e q u e s t ) ;
$ d i s p l a y ( " g r a n t ␣=␣%b " , t e s t _ g r a n t ) ;
@( negedge c l k ) ;
i f ( tes t _ ne x tG r a nt != expectedNextGrant )
begin
sticky = 1;
$ d i s p l a y ( " Expected ␣ next ␣ g r a n t ␣=␣%b , ␣ Actual ␣=␣%b " ,
expectedNextGrant , t es t _n e x tG r an t ) ;
end
else
$ d i s p l a y ( " next ␣ g r a n t ␣=␣%b " , t es t _n e x tG r an t ) ;

// t e s t c a s e 7
// r e q u e s t = 0000 _0010
// g r a n t = 0000 _0010
I-18

// nextGrant = 0000 _0010


// nextGrant = 1111 _1100 ?? maybe?
@( p o s e d g e c l k )
t e s t _ r e q u e s t = 8 ' b0000_0010 ;
t e s t _ g r a n t = 8 ' b0000_0010 ;
expectedNextGrant = 8 ' b0000_0010 ;
$ d i s p l a y ( "−−−−−Test ␣ c a s e ␣7−−−−−" ) ;
$ d i s p l a y ( " Request ␣=␣%b " , t e s t _ r e q u e s t ) ;
$ d i s p l a y ( " g r a n t ␣=␣%b " , t e s t _ g r a n t ) ;
@( negedge c l k ) ;
i f ( tes t _ ne x tG r a nt != expectedNextGrant )
begin
sticky = 1;
$ d i s p l a y ( " Expected ␣ next ␣ g r a n t ␣=␣%b , ␣ Actual ␣=␣%b " ,
expectedNextGrant , t es t _n e x tG r an t ) ;
end
else
$ d i s p l a y ( " next ␣ g r a n t ␣=␣%b " , t es t _n e x tG r an t ) ;

// t e s t c a s e 8
// r e q u e s t = 0000 _0010
// g r a n t = 0
// nextGrant = 0000 _0010
@( p o s e d g e c l k )
t e s t _ g r a n t = 8 ' b0000_0010 ;
t e s t _ g r a n t = 8 ' b0 ;
expectedNextGrant = 8 ' b0000_0010 ;
$ d i s p l a y ( "−−−−−Test ␣ c a s e ␣8−−−−−" ) ;
$ d i s p l a y ( " Request ␣=␣%b " , t e s t _ r e q u e s t ) ;
$ d i s p l a y ( " g r a n t ␣=␣%b " , t e s t _ g r a n t ) ;
@( negedge c l k ) ;
i f ( tes t _ ne x tG r a nt != expectedNextGrant )
begin
sticky = 1;
$ d i s p l a y ( " Expected ␣ next ␣ g r a n t ␣=␣%b , ␣ Actual ␣=␣%b " ,
expectedNextGrant , t es t _n e x tG r an t ) ;
end
else
$ d i s p l a y ( " next ␣ g r a n t ␣=␣%b " , t es t _n e x tG r an t ) ;

@( p o s e d g e c l k )
r e s e t = 1 ' b1 ;
I-19

@( p o s e d g e c l k )
r e s e t = 1 ' b0 ;

@( p o s e d g e c l k ) ;
@( p o s e d g e c l k ) ;
@( p o s e d g e c l k ) ;

i f ( s t i c k y == 1 )
$ d i s p l a y ( " Test ␣ f a i l e d " ) ;
else
$ d i s p l a y ( " Test ␣ p a s s e d " ) ;

$finish ;

end

// c h e c k o u t p u t i n p a r a l l e l on n e g a t i v e e d g e
// a l w a y s @( n e g e d g e c l k )
// b e g i n
// f o r ( k = 0 ; k < CHANNELS; k = k+1)

// begin
// make s u r e i n p u t i s v a l i d ( one h o t )
// i f ( t e s t _ s e l O n e H o t == 1 << k )
// c h e c k i f DUT o u t p u t matches e x p e c t e d o u t p u t
// i f ( t e s t _ d a t a O u t !== dataArray [ k ] )
// begin
// d i s p l a y u s e f u l i n f o r m a t i o n i f t h e o u t p u t s don ' t
match
// $ d i s p l a y ( " Wrong o u t p u t a t %0t " , $time ) ;
// $ d i s p l a y ( " E x p e c t e d %H, A c t u a l %H" , dataArray [ k ] ,
test_dataOut ) ;

// s t o p i f we s e e e r r o r
// $ f i n i s h ;
// end

// end

// c ou n t waves
I-20

// waveCounter = waveCounter + 1 ;

// s t o p i f we l o o p e d t h r o u g h a l l c h a n n e l v a l u e s (∗2 t o s e e some
extra
// l e n g t h )
// i f ( waveCounter >= CHANNELS∗2)
// $finish ;
// end

// c l o c k g e n e r a t i o n
always #(CLOCK_PERIOD/ 2 )
clk = ~clk ;

endmodule
I-21

Listing I.5: Grant Module

// GRANT module
//
//
module GRANT
#(
parameter CHANNELS = 8 , // t o t a l number o f r e q u e s t o r s
parameter WIDTH = 3 2 , // t h e w i d t h o f each r e q u e s t o r ' s
weight
parameter WEIGHTLIMIT = 16
)
(
reset ,
clk ,
scan_in0 ,
scan_in1 ,
scan_in2 ,
scan_in3 ,
scan_in4 ,
scan_enable ,
test_mode ,
scan_out0 ,
scan_out1 ,
scan_out2 ,
scan_out3 ,
scan_out4 ,

// i n p u t
request , // r e q u e s t i n p u t
nextGrant , // nextGrant from NGPRC
weight , // w e i g h t o f c u r r e n t g r a n t

// o u t p u t
grant // g r a n t o u t p u t
);

input
reset , // system r e s e t
clk ; // system c l o c k

input
scan_in0 , // t e s t scan mode d a t a i n p u t
I-22

scan_in1 , // test scan mode data input


scan_in2 , // test scan mode data input
scan_in3 , // test scan mode data input
scan_in4 , // test scan mode data input
scan_enable , // test scan mode enable
test_mode ; // test mode

output
scan_out0 , // test scan mode data output
scan_out1 , // test scan mode data output
scan_out2 , // test scan mode data output
scan_out3 , // test scan mode data output
scan_out4 ; // test scan mode data output

// i n p u t
i n p u t [ (CHANNELS−1) : 0 ] r e q u e s t ;
i n p u t [ ( CHANNELS−1) : 0 ] nextGrant ;
i n p u t [ (WIDTH−1) : 0 ] w e i g h t ;

// o u t p u t
output r e g [ ( CHANNELS−1) : 0 ] g r a n t ;

// i n t e r n a l r e g i s t e r s
r e g [ (WIDTH−1) : 0 ] s_counter ;
r e g [ (CHANNELS−1) : 0 ] s _ r e q u e s t ;
r e g [ (WIDTH−1) : 0 ] s_weight ;
// r e g u p d a t e ;
//−−− I n t e r n a l C o n s t a n t s −−−//
l o c a l p a r a m SIZE = 4 ;

// STATES
r e g [ ( SIZE−1) : 0 ] s t a t e ;
l o c a l p a r a m RESET = ' b0001 ; // ' b00001
l o c a l p a r a m GRANT_PROCESS = ' b0010 ; // ' b00100
l o c a l p a r a m COUNT = ' b0100 ; // ' b01000
l o c a l p a r a m GETWEIGHT = ' b1000 ; // ' b10000

//−−− Code S t a r t s −−//

// r e g i s t e r i / d e l a y r e q u e s t
always@ ( p o s e d g e c l k , p o s e d g e r e s e t )
begin : requestDelay
I-23

i f ( r e s e t == 1 ' b1 )
s_request = 0;
else
s_request = request ;
end

// a l w a y s b l o c k f o r s t a t e t r a n s i t i o n
always@ ( p o s e d g e c l k , p o s e d g e r e s e t )
begin : grantStateTransition
// r e s e t c o n d i t i o n
i f ( r e s e t == 1 ' b1 )
begin
state = 0;
end

// o u t o f r e s e t
else
begin
// s t a t e t r a n s i s i t o n
case ( state )
// g r a n t p r o c e s s t h i s o u t p u t g r a n t
GRANT_PROCESS :
begin
// i f t h e r e i s r e q u e s t
// go t o COUNT s t a t e t o co u nt
i f ( g r a n t != 0 )
s t a t e = GETWEIGHT;

// j u s t s t a y h e r e and p r o c e s s n e x t
else
state = state ;

end

GETWEIGHT :
begin
s t a t e = COUNT;
end

// c ou n t c l o c k c y c l e a c c o r d i n g t o w e i g h t
COUNT :
begin
// i f c o u n t e r i s up
I-24

// move t o g r a n t n e x t
i f ( s_counter >= s_weight )
s t a t e = GRANT_PROCESS;

// f a i r n e s s l i m i t s e t by u s e r
// d e f a u l t i s 16
e l s e i f ( s_counter >= WEIGHTLIMIT)
s t a t e = GRANT_PROCESS;

// e l s e
// k e e p c o u n t i n g
else
state = state ;

end

// i f s t a t e m a c h i n e n e v e r g o e s o u t o f wack
default :
begin
s t a t e = GRANT_PROCESS;
end
endcase

end

end

// o u t p u t l o g i c
always@ ( p o s e d g e c l k , p o s e d g e r e s e t )
b e g i n : gr a n t S t a t e M a c h i n e O u t p u t L o g i c
i f ( r e s e t == 1 ' b1 )
begin
grant = 0;
s_counter = 0 ;
s_weight = 0 ;
end
else
case ( state )
RESET :
begin
// r e s e t e v e r y t h i n g i n r e s e t s t a t e

grant = 0;
I-25

s_counter = 0 ;
//s_mask = ~ 0 ;
end

GRANT_PROCESS :
begin
// u p d a t e mask
//s_mask = nextGrant & (~ nextGrant + 1) ;

// g r a n t i n g l o g i c
g r a n t = r e q u e s t & nextGrant & (~ nextGrant + 1 ) ;

// i t t a k e s 3 c y c l e t o l o o k b a c k h e r e
// so s e t t h e c o u n t e r f o r when w e i g h t >= 2
s_counter = 2 ;
end

GETWEIGHT:
begin
s_weight = w e i g h t ;
end

COUNT :
begin
// c ou n t up u n t i l w e i g h t i s r e a c h e d a c c o u n t f o r c l o c k
cycle
s_counter = s_counter + 1 ;

// no change t o g r a n t
grant = grant ;
end

// i f s t a t e m a c h i n e n e v e r g o e s o u t o f wack
default :
begin
grant = grant ;
s_counter = s_counter ;

end

endcase
end
I-26

endmodule // GRANT
I-27

Listing I.6: Round Robin Arbiter Module

// RRBTOP module
// Top l e v e l o f Round Robin A r b i t e r
// This module c o n n e c t s MUX, Next Grant P r e c a l c u l a t o r and Grant
statemachine
// I n p u t : r e q u e s t , w e i g h t bus
// Output : g r a n t
`include " i n c l u d e / RRB_verification . h"

module RRBTOP
#(
parameter CHANNELS = `CHANNELS,
parameter WIDTH = `WIDTH,
parameter WEIGHTLIMIT = `WEIGHTLIMIT
)
(
reset ,
clk ,

// i n p u t t o RRB
request ,
weight , // w e i g h t bus each h a v i n g b i t s i z e o f WIDTH f o r
each c h a n n e l
// o u t p u t from RRB
grant ,

scan_in0 ,
scan_in1 ,
scan_in2 ,
scan_in3 ,
scan_in4 ,
scan_enable ,
test_mode ,
scan_out0 ,
scan_out1 ,
scan_out2 ,
scan_out3 ,
scan_out4
);

input
I-28

reset , // system r e s e t
clk ; // system c l o c k

input
scan_in0 , // test scan mode data input
scan_in1 , // test scan mode data input
scan_in2 , // test scan mode data input
scan_in3 , // test scan mode data input
scan_in4 , // test scan mode data input
scan_enable , // test scan mode enable
test_mode ; // test mode

output
scan_out0 , // test scan mode data output
scan_out1 , // test scan mode data output
scan_out2 , // test scan mode data output
scan_out3 , // test scan mode data output
scan_out4 ; // test scan mode data output

i n p u t [ (CHANNELS−1) : 0 ] r e q u e s t ;
i n p u t [ (CHANNELS∗WIDTH)−1 : 0 ] w e i g h t ;

output w i r e [ ( CHANNELS−1) : 0 ] g r a n t ;

w i r e [ (CHANNELS−1) : 0 ] s_selOneHot ;
w i r e [ (WIDTH−1) : 0 ] s_weight ;
w i r e [ (CHANNELS−1) : 0 ] s_nextGrant ;

// COMBINATIONAL SECTION //
a s s i g n g r a n t = s_selOneHot ;

// MUX
MUX #(
.WIDTH(WIDTH) ,
.CHANNELS(CHANNELS)
)
MUX(
. reset ( reset ) ,
. clk ( clk ) ,
I-29

. scan_in0 ( scan_in0 ) ,
. scan_in1 ( scan_in1 ) ,
. scan_in2 ( scan_in2 ) ,
. scan_in3 ( scan_in3 ) ,
. scan_in4 ( scan_in4 ) ,
. scan_enable ( scan_enable ) ,
. test_mode ( test_mode ) ,
. scan_out0 ( scan_out0 ) ,
. scan_out1 ( scan_out1 ) ,
. scan_out2 ( scan_out2 ) ,
. scan_out3 ( scan_out3 ) ,
. scan_out4 ( scan_out4 ) ,

// i n p u t
. selOneHot ( s_selOneHot ) ,
. dataInBus ( w e i g h t ) ,

// o u t p u t
. dataOut ( s_weight )

);

NGPRC #(
.CHANNELS(CHANNELS)
)
NGPRC(
. reset ( reset ) ,
. clk ( clk ) ,
. scan_in0 ( scan_in0 ) ,
. scan_in1 ( scan_in1 ) ,
. scan_in2 ( scan_in2 ) ,
. scan_in3 ( scan_in3 ) ,
. scan_in4 ( scan_in4 ) ,
. scan_enable ( scan_enable ) ,
. test_mode ( test_mode ) ,
. scan_out0 ( scan_out0 ) ,
. scan_out1 ( scan_out1 ) ,
. scan_out2 ( scan_out2 ) ,
. scan_out3 ( scan_out3 ) ,
. scan_out4 ( scan_out4 ) ,

// i n p u t
. request ( request ) ,
I-30

. g r a n t ( s_selOneHot ) ,

// o u t p u t
. nextGrant ( s_nextGrant )

);

GRANT #(
.CHANNELS(CHANNELS) ,
.WIDTH(WIDTH) ,
. WEIGHTLIMIT(WEIGHTLIMIT)
)
GRANT(
. reset ( reset ) ,
. clk ( clk ) ,
. scan_in0 ( scan_in0 ) ,
. scan_in1 ( scan_in1 ) ,
. scan_in2 ( scan_in2 ) ,
. scan_in3 ( scan_in3 ) ,
. scan_in4 ( scan_in4 ) ,
. scan_enable ( scan_enable ) ,
. test_mode ( test_mode ) ,
. scan_out0 ( scan_out0 ) ,
. scan_out1 ( scan_out1 ) ,
. scan_out2 ( scan_out2 ) ,
. scan_out3 ( scan_out3 ) ,
. scan_out4 ( scan_out4 ) ,

// i n p u t
. request ( request ) ,
. nextGrant ( s_nextGrant ) ,
. w e i g h t ( s_weight ) ,

// o u t p u t
. g r a n t ( s_selOneHot )

);
endmodule // RRB
I-31

Listing I.7: Round Robin Arbiter Test Module

module t e s t ;
l o c a l p a r a m WIDTH = 3 2 ;
l o c a l p a r a m CHANNELS = 4 ;
l o c a l p a r a m WEIGHTLIMIT = 1 0 0 ;

// c l o c k p e r i o d
l o c a l p a r a m CLOCK_PERIOD = 2 0 ; // 20 ns (500MHZ)

w i r e scan_out0 , scan_out1 , scan_out2 , scan_out3 , scan_out4 ;


reg clk , r e s e t ;
r e g scan_in0 , scan_in1 , scan_in2 , scan_in3 , scan_in4 , scan_enable ,
test_mode ;

// i n p u t s
r e g [ (CHANNELS∗WIDTH−1) : 0 ] t e s t _ w e i g h t ;
r e g [ (CHANNELS−1) : 0 ] t e s t _ r e q u e s t ;
// r e g t e s t _ a c k ;

// o u t p u t
w i r e [ (CHANNELS−1) : 0 ] t e s t _ g r a n t ;

//
r e g [ (WIDTH−1) : 0 ] tempData ;

// f l o w c o n t r o l f l a g s
integer j = 0;

RRBTOP #(
.CHANNELS(CHANNELS) ,
.WIDTH(WIDTH) ,
. WEIGHTLIMIT(WEIGHTLIMIT)
)
top (
. reset ( reset ) ,
. clk ( clk ) ,
. scan_in0 ( scan_in0 ) ,
. scan_in1 ( scan_in1 ) ,
. scan_in2 ( scan_in2 ) ,
. scan_in3 ( scan_in3 ) ,
I-32

. scan_in4 ( scan_in4 ) ,
. scan_enable ( scan_enable ) ,
. test_mode ( test_mode ) ,
. scan_out0 ( scan_out0 ) ,
. scan_out1 ( scan_out1 ) ,
. scan_out2 ( scan_out2 ) ,
. scan_out3 ( scan_out3 ) ,
. scan_out4 ( scan_out4 ) ,

// i n p u t
//
. request ( test_request ) ,
. weight ( test_weight ) ,
// . ack ( t e s t _ a c k ) ,

// o u t p u t
. grant ( test_grant )

);

initial
begin
$ t i m e f o r m a t ( −9 ,2 , " ns " , 1 6 ) ;
` i f d e f SDFSCAN
$ s d f _ a n n o t a t e ( " s d f /ADDC_tsmc18_scan . s d f " , t e s t . top ) ;
`endif
c l k = 1 ' b0 ;
r e s e t = 1 ' b1 ;
scan_in0 = 1 ' b0 ;
scan_in1 = 1 ' b0 ;
scan_in2 = 1 ' b0 ;
scan_in3 = 1 ' b0 ;
scan_in4 = 1 ' b0 ;
scan_enable = 1 ' b0 ;
test_mode = 1 ' b0 ;

// t e s t _ a c k = 1 ' b0 ;
test_request = 0;

// s e t t h e v e r y f i r s t w e i g h t t o 2 ( c h a n n e l 0)
tempData = 3 ;
I-33

test_weight = 3;

// i n p u t w e i g h t d a t a bus g e n e r a t i o n
f o r ( j = 1 ; j < CHANNELS; j = j +1)
begin
// m a n i p u l a t e t e s t d a t a f o r each c h a n n e l ( i n c r e m e n t by 2 i n
this
// c a s e )
tempData = tempData + 2 ;

// s e t w e i g h t d a t a bus by s h i f t i n g and b i t w i s e or
t e s t _ w e i g h t = t e s t _ w e i g h t | ( tempData << WIDTH∗ j ) ;

end

// p u l l r e s e t h i g h
@( p o s e d g e c l k ) ;
@( p o s e d g e c l k ) ;
r e s e t = 1 ' b0 ;

@( p o s e d g e c l k ) ;
t e s t _ r e q u e s t = ' b1001 ;

#100

@( p o s e d g e c l k ) ;
// t e s t _ a c k = 1 ' b1 ;
t e s t _ r e q u e s t = ' b0010 ;

@( p o s e d g e c l k ) ;
// t e s t _ a c k = 1 ' b0 ;

#160
@( p o s e d g e c l k ) ;
// t e s t _ a c k = 1 ' b1 ;
t e s t _ r e q u e s t = ' b0001 ;

@( p o s e d g e c l k ) ;
// t e s t _ a c k = 1 ' b0 ;

#500
$finish ;
I-34

end

// c l o c k g e n e r a t i o n
always #(CLOCK_PERIOD/ 2 )
clk = ~clk ;

endmodule
Appendix II

Test Bench Source Code


Listing II.1: Requestor Module

// requestor . sv
// r e q u e s t o r module
// t h i s module g e n e r a t e s
// random r e q u e s t (0 or 1)
// w e i g h t (0 t o 2^32−1)

class requestor ;
rand b i t r e q u e s t ; // r e q u e s t
rand b i t [ 3 1 : 0 ] w e i g h t ; // w e i g h t

int seed ;
i n t weightLow ;
i n t weightHigh ;

// c o n s t r a i n t w e i g h t b e t w e e n t h e l i m i t s
c o n s t r a i n t weight_range {
w e i g h t i n s i d e { [ weightLow : weightHigh ] } ;
}

// c o n s t r u c t o r
f u n c t i o n new ( i n t s e e d = 1 , i n t weightLow = 2 , i n t weightHigh =
100) ;
this . request = 0;
t h i s . w e i g h t = weightLow ;
II-36

t h i s . seed = seed ;
t h i s . weightLow = weightLow ;
t h i s . weightHigh = weightHigh ;

// i n i t i a l i z e random seed
t h i s . srandom ( s e e d ) ;

e n d f u n c t i o n : new

endclass
II-37

Listing II.2: Generator Module

// generator . sv
// generator class
// This c l a s s g e n e r a t e s random s t i m u l u s
// i n t h i s case , i t i n s t a n t i a t e s m u l t i p l e r e q u e s t o r s

`include " i n c l u d e / RRB_verification . h"

class generator ;
requestor req ;

// c o n s t r u c t o r method
f u n c t i o n new ( r e q u e s t o r r e q ) ;
t h i s . req = req ;
e n d f u n c t i o n : new

// g e n e r a t e random r e q u e s t s
extern function void generate_requestor ;

// g e t r e q u e s t
extern function bit get_request ;

// g e t w e i g h t
e x t e r n f u n c t i o n b i t [`WIDTH−1 : 0 ] get_weight ;

endclass : generator

//−−−−−−−−−−E x t e r n a l Methods−−−−−−−−−//

// g e n e r a t e f u n c t i o n
// no a r g i n p u t
// randomize t h e r e q u e s t o r
function void generator : : generate_requestor ;
begin : randomize_requestor

// g e n e r a t e random r e q u e s t / w e i g h t i n r e q u e s t o r
a s s e r t ( r e q . randomize ( ) ) ;

i f (`DEBUG_GENERATOR)
$ d i s p l a y ( " g e n e r a t e d ␣ r e q u e s t o r ␣ : ␣%p\n " , r e q ) ;

end : r a n d o m i z e _ r e q u e s t o r
II-38

endfunction : generate_requestor

// g e t method f o r r e q u e s t o r ' s r e q u e s t
function bit generator : : get_request ;
begin
return req . request ;
end

endfunction : get_request

// g e t method f o r r e q u e s t o r ' s w e i g h t
f u n c t i o n b i t [`WIDTH−1 : 0 ] g e n e r a t o r : : get_weight ;
begin
return req . weight ;
end
e n d f u n c t i o n : get_weight
II-39

Listing II.3: Agent Module

// agent . sv
// agent c l a s s
// a g e n t i n s t a n t i a t e s g e n e r a t o r module
// u s i n g t h a t g e n e r a t o r t o g e n e r a t e random r e q u e s t s

`include " i n c l u d e / RRB_verification . h"

c l a s s agent ;
g e n e r a t o r gen ;
b i t [`CHANNELS−1 : 0 ] r e q u e s t s ;
b i t [ ( `CHANNELS∗`WIDTH)−1 : 0 ] w e i g h t s ;

b i t [`CHANNELS−1 : 0 ] g o l d e n _ g r a n t s ;
i n t golden_grant_weights [`CHANNELS] = ' { d e f a u l t : 0 } ;
i n t temp_weights [`CHANNELS] = ' { d e f a u l t : 0 } ;

// c o n s t r u c t o r method
f u n c t i o n new ( g e n e r a t o r gen ) ;
t h i s . gen = gen ;
this . requests = 0;
t h i s . weights = 0;

t h i s . golden_grants = 0 ;
t h i s . golden_grant_weights = ' { d e f a u l t : 0 } ;
t h i s . temp_weights = ' { d e f a u l t : 0 } ;
e n d f u n c t i o n : new

// g e n e r a t e new r e q u e s t s
extern function void generate_requests ;

e n d c l a s s : agent

//−−−−−−−−−−E x t e r n a l Methods−−−−−−−−−−//

// g e n e r a t e _ r e q u e s t s f u n c t i o n
// no a r g i n p u t
// g e n e r a t e n number o f r e q u e s t o r s
f u n c t i o n void agent : : generate_requests ;
b e g i n : generateNewRequests

// o n l y g e t g o l d e n v e c t o r i f r e q u e s t s a r e not z e r o
II-40

// by g e t t i n g g o l d e n v e c t o r a t t h e s t a r t o f t h i s r o u t i n e
// we a r e e s s e n t i a l l y d e l a y i n g t h e u p d a t e by one t e s t v e c t o r
set
// t h i s a l l o w s g o l d e n v e c t o r s t o be i n sync w i t h c h e c k e r /
monitor /DUT
i f ( r e q u e s t s != 0 )
begin
// g o l d e n t e s t d a t a t o c h e c k DUT
golden_grants = r e q u e s t s ;
golden_grant_weights = temp_weights ;

$ d i s p l a y ( " r e q u e s t ␣ a t ␣ update ␣%b " , r e q u e s t s ) ;


$ d i s p l a y ( " w e i g h t ␣ a t ␣ update ␣%h " , w e i g h t s ) ;
$ d i s p l a y ( " g o l d e n ␣ update ␣ a t ␣%g " , $time ) ;
end

// r e s e t w e i g h t s
weights = 0;

// l o o p t h r o u g h t o g e n e r a t e n random r e q u e s t s
f o r ( i n t i = 0 ; i < `CHANNELS; i ++)
begin
gen . g e n e r a t e _ r e q u e s t o r ( ) ;

// random r e q u e s t d a t a
r e q u e s t s [ i ] = gen . g e t _ r e q u e s t ( ) ;
w e i g h t s = w e i g h t s | gen . get_weight ( ) << ( i ∗ `WIDTH) ;
temp_weights [ i ] = gen . get_weight ( ) ;

// d i s p l a y i f debug a g e n t f l a g i s s e t
// debug o n l y
i f (`DEBUG_AGENT)
begin
// $ d i s p l a y ( " i = %d " , i ) ;
// $ d i s p l a y ( " r e q u e s t = %d " , gen . g e t _ r e q u e s t ( ) ) ;
// $ d i s p l a y ( " w e i g h t = %d " , gen . g e t _ w e i g h t ( ) ) ;
end

end

// debug
i f (`DEBUG_AGENT)
II-41

begin
$ d i s p l a y ( " r e q u e s t s ␣=␣%b " , r e q u e s t s ) ;
$ d i s p l a y ( " w e i g h t s ␣=␣%h " , w e i g h t s ) ;

$ d i s p l a y ( " g o l d e n ␣ g r a n t s ␣=␣%b " , g o l d e n _ g r a n t s ) ;

f o r ( i n t i = 0 ; i < `CHANNELS; i ++)


begin
$ d i s p l a y ( " g o l d e n ␣ g r a n t ␣ w e i g h t s ␣%d␣=␣%h " , i ,
golden_grant_weights [ i ] ) ;
end
end

end : generateNewRequests
endfunction : generate_requests
II-42

Listing II.4: Driver Module

// d r i v e r . s v
// d r i v e r c l a s s
`include " i n c l u d e / RRB_verification . h"

class driver ;

// h a n d l e f o r i n t e r f a c e
virtual intf_rrb i n t f ;

// h a n d l e f o r a g e n t
agent agt ;

// e v e n t h a n d l e
event e_start ;
e v e n t e_drv_done ;

// c o n s t r u c t o r method
f u n c t i o n new ( v i r t u a l i n t f _ r r b i n t f , a g e n t agt , e v e n t e_drv_done ) ;
this . intf = intf ;
t h i s . agt = agt ;
t h i s . e_drv_done = e_drv_done ;

e n d f u n c t i o n : new

// r e s e t method
extern task r e s e t () ;

// d r i v e new d a t a
e x t e r n t a s k drive_new_data ( ) ;

// e v e n t l o g i c
extern task event_logic () ;
endclass : driver

//−−−−−−−−−−E x t e r n a l Methods−−−−−−−−−−//
// d r i v e new d a t a
t a s k d r i v e r : : drive_new_data ( ) ;
// we need t o know how l o n g t o w a i t t o know when d r i v e new d a t a
// so w a i t f o r w e i g h t c y c l e s b e f o r e s e n d i n g new d a t a
b i t [ ( `CHANNELS∗`WIDTH)−1 : 0 ] w a i t C y c l e s , temp ;
waitCycles = 0;
II-43

temp = 0 ;

// g e t t h e sum o f a l l t h e w e i g h t s
f o r ( i n t i = 0 ; i < `CHANNELS; i ++)
begin
temp = a g t . w e i g h t s >> ( i ∗`WIDTH) ;
w a i t C y c l e s = w a i t C y c l e s + temp [`WIDTH−1 : 0 ] ∗ ( a g t . r e q u e s t s [ i
]) ;
end

// debug o n l y
i f (`DEBUG_DRIVER)
begin
$ d i s p l a y ( " a g t ␣%p\n " , a g t ) ;
$ d i s p l a y ( " w a i t C y c l e s ␣%d\n " , w a i t C y c l e s ) ;
end

// send r e q u e s t t o DUT s y n c h r o n o u s l y
// o n l y need t o w a i t i f w a i t C y c l e i s not z e r o
i f ( waitCycles > 0)
begin
// w a i t f o r w a i t C y c l e s i f o r DUT t o perform a r b i t e r a t i o n
f o r ( i n t i = 0 ; i < ( w a i t C y c l e s ) ; i ++)
begin
@( p o s e d g e i n t f . DRIVER . c l k ) ;
i n t f . DRIVER . r e q u e s t = a g t . r e q u e s t s ;
i n t f . DRIVER . w e i g h t = a g t . w e i g h t s ;
end

// a f t e r w a i t c y c l e i s done , t e l l e v e n t l o g i c t o s t a r t c o u n t e r
−> e _ s t a r t ;
// $ d i s p l a y ( " s t a r t a t %g " , $time ) ;
end

e n d t a s k : drive_new_data

// Event l o g i c
// t o w a i t 2 c y c l e s a f t e r d r i v e r i s done d r i v i n g
// t o sync up w i t h end o f DUT o u t p u t
task driver : : event_logic () ;
forever
begin
//@( p o s e d g e i n t f .DRIVER. c l k ) ;
II-44

@( e _ s t a r t ) ;
// $ d i s p l a y ( " c a u g h t a t %g " , $time ) ;

// r e p e a t ( 2 )
//@( p o s e d g e i n t f .DRIVER. c l k ) ;

−> e_drv_done ;
// $ d i s p l a y ( " d r i v e r done i s s u e d " ) ;
end
endtask : event_logic

// R e s e t Method
task driver : : r e s e t () ;
// i n i t i a l i z e e v e r y t h i n g
i n t f . DRIVER . r e s e t = 1 ' b0 ;
i n t f . DRIVER . r e q u e s t = 0 ;
i n t f . DRIVER . w e i g h t = 0 ;

// r e s e t on n e g a t i v e e d g e
@( negedge i n t f . DRIVER . c l k ) ;
i n t f . DRIVER . r e s e t = 1 ' b1 ;

// w a i t f o r a few c y c l e s
@( negedge i n t f . DRIVER . c l k ) ;
@( negedge i n t f . DRIVER . c l k ) ;

i n t f . DRIVER . r e s e t = 1 ' b0 ;
// w a i t f o r a few c y c l e s
@( negedge i n t f . DRIVER . c l k ) ;
@( negedge i n t f . DRIVER . c l k ) ;

endtask : r e s e t
II-45

Listing II.5: Monitor Module

// monitor . s v
// monitor c l a s s
// Monitor c a p t u r e s DU o u t p u t

`include " i n c l u d e / RRB_verification . h"

class monitor ;

// h a n d l e f o r i n t e r f a c e
virtual intf_rrb i n t f ;

// DUT o u t p u t v e c t o r s
b i t [`CHANNELS−1 : 0 ] dut_grants ;
i n t dut_weight_array [`CHANNELS] = ' { d e f a u l t : 0 } ;

// d a t a t o be s e n t t o c h e c k e r
b i t [`CHANNELS−1 : 0 ] mon_grants ;
i n t mon_weight_array [`CHANNELS] = ' { d e f a u l t : 0 } ;

// e v e n t h a n d l e s
e v e n t e_drv_done ;
e v e n t e_mon_done ;

// b i t t o i n d i c a t e d a t a ne ed s t o be c l e a r e d
bit clearData ;

// c o n s t r u c t o r method
f u n c t i o n new ( v i r t u a l i n t f _ r r b i n t f , e v e n t e_drv_done , e v e n t
e_mon_done ) ;
this . intf = intf ;

this . dut_grants = 0 ;
this . dut_weight_array = ' { d e f a u l t : 0 } ;
this . mon_grants = 0 ;
this . dut_weight_array = ' { d e f a u l t : 0 } ;

t h i s . e_drv_done = e_drv_done ;
t h i s . e_mon_done = e_mon_done ;

t h i s . clearData = 0;
e n d f u n c t i o n : new
II-46

// monitor t h e o u t p u t
e x t e r n t a s k run ;

// e v e n t l o g i c
extern task event_logic ;
e n d c l a s s : monitor

//−−−−−−−−−−E x t e r n a l Methods−−−−−−−−−−//
// run method
t a s k monitor : : run ;

// w a i t time f o r d r i v e r

forever
begin

// c a p t u r e d a t a on p o s i t i v e e d g e o f c l o c k
@( p o s e d g e i n t f .MONITOR. c l k ) ;
i f ( i n t f .MONITOR. g r a n t != 0 )
begin

// i f we need t o c l e a r c o u n t e r s , do i t f i r s t b e f o r e
couting again
i f ( clearData )
begin
dut_grants = 0 ;
dut_weight_array = ' { d e f a u l t : 0 } ;
clearData = 0;
end

dut_grants [ $ c l o g 2 ( i n t f .MONITOR. g r a n t ) ] = 1 ;
dut_weight_array [ $ c l o g 2 ( i n t f .MONITOR. g r a n t ) ] =
dut_weight_array [ $ c l o g 2 ( i n t f .MONITOR. g r a n t ) ] + 1 ;

end

end

e n d t a s k : run
II-47

// e v e n t l o g i c
// when d r i v e r i s done d r i v i n g , i t means one t e s t v e c t o r i s done
// we need t o r e g i s t e r d a t a f o r monitor t o be read
// a t t h e same time s e t c l e a r b i t t o c l e a r o u t c o u n t e r s
t a s k monitor : : e v e n t _ l o g i c ;
forever
begin
//@( p o s e d g e i n t f .MONITOR. c l k ) ;
// w a i t ( e_drv_done . t r i g g e r e d ) ;
@( e_drv_done ) ;
$ d i s p l a y ( " e v e n t t r i g g e r e d ␣ a t ␣%g " , $time ) ;

repeat (2)
@( p o s e d g e i n t f .MONITOR. c l k ) ;

// d r i v e r /DUT f i n i s h e d one s e t o f t e s t v e c t o r s
// r e g i s t e r / copy o u t p u t f o r monitor
mon_grants = dut_grants ;
mon_weight_array = dut_weight_array ;

// i n d i c a t e monitor i s r e a d y f o r c h e c k e r
−> e_mon_done ;

// i f we f i n i s h e d one s e t o f t e s t v e c t o r s
// we need t o c l e a r c o u n t e r s
clearData = 1;

i f (`DEBUG_MONITOR)
begin
$ d i s p l a y ( "−−−" ) ;
$ d i s p l a y ( " dut ␣ g r a n t ␣=␣%b␣ a t ␣%g " , dut_grants , $time ) ;
$ d i s p l a y ( "mon␣ g r a n t ␣=␣%b␣ a t ␣%g " , mon_grants , $time ) ;

// $ d i s p l a y ( " w e i g h t = %h " , dut_weight_array [ $ c l o g 2 ( i n t f .


MONITOR. g r a n t ) ] ) ;
f o r ( i n t i = 0 ; i < `CHANNELS; i ++)
begin
$ d i s p l a y ( " dut ␣ w e i g h t ␣%d␣=␣%h " , i , dut_weight_array [ i ] )
;
$ d i s p l a y ( "mon␣ w e i g h t ␣%d␣=␣%h " , i , mon_weight_array [ i ] )
;

end
II-48

end
end
endtask : event_logic
II-49

Listing II.6: Checker Module

// c h e c k . s v
// c h e c k c l a s s
// g e t o u t p u t o f DUT and a g e n t d a t a
// and compare and r e c o r e d i n s c o r e b o a r d

`include " i n c l u d e / RRB_verification . h"

c l a s s check ;
// c l a s s h a n d l e s
s c o r e b o a r d sb ;
agent agt ;
monitor mon ;

// e v e n t h a n d l e s
e v e n t e_mon_done ;
e v e n t e_drv_done ;

// g o l d e n t e s t v e c t o r s
b i t [`CHANNELS−1 : 0 ] chk_golden_grants ;
i n t chk_golden_grant_weights [`CHANNELS] = ' { d e f a u l t : 0 } ;

// c o n s t r u c t o r method
f u n c t i o n new ( s c o r e b o a r d sb , a g e n t agt , monitor mon , e v e n t
e_mon_done , e v e n t e_drv_done ) ;
t h i s . sb = sb ;
t h i s . agt = agt ;
t h i s . mon = mon ;

t h i s . e_mon_done = e_mon_done ;
t h i s . e_drv_done = e_drv_done ;

t h i s . chk_golden_grants = 0 ;
t h i s . chk_golden_grant_weights = ' { d e f a u l t : 0 } ;
e n d f u n c t i o n : new

// t a s k t o c h e c k t h e o u t p u t o f DUT
e x t e r n t a s k check_output ;

// t e s t t o u p d a t e t h e g o l d e n d a t a
// i t i s a l w a y s running b u t i n sync w i t h end o f d r i v e r done e v e n t
II-50

e x t e r n t a s k update_golden_data ;

e n d c l a s s : check

//−−−−−−−−−−E x t e r n a l Methods−−−−−−−−−−//
// c h e c k t h e o u t p u t o f DUT and Agent g o l d e n d a t a
t a s k check : : check_output ( ) ;
forever
begin
@( e_mon_done ) ;

i f (`DEBUG_CHECKER)
begin
$ d i s p l a y ( " l o c a l ␣ g o l d e n ␣ g r a n t ␣=␣%b " , chk_golden_grants ) ;
$ d i s p l a y ( "mon␣DUT␣ g r a n t ␣=␣%b␣ a t ␣%g " , mon . mon_grants , $time
);

f o r ( i n t i = 0 ; i < `CHANNELS; i ++)


begin
$ d i s p l a y ( "mon␣DUT␣ w e i g h t ␣%d␣=␣%h " , i , mon .
mon_weight_array [ i ] ) ;
$ d i s p l a y ( " l o c a l ␣ g o l d e n ␣ w e i g h t ␣%d␣=␣%h " , i ,
chk_golden_grant_weights [ i ] ) ;
end
end

// l o o p t h r o u g h a l l t h e c h a n n e l s and c h e c k t h e o u t p u t
f o r ( i n t i = 0 ; i < `CHANNELS; i ++)
begin
// i f t h e r e q u e s t i s 1 , c h e c k t h e w e i g h t
i f ( chk_golden_grants [ i ] == 1 )
begin
// $ d i s p l a y ( " g o l d e n i n d e x p o s i t i o n = %h " , i ) ;
// $ d i s p l a y ( " d u t b i t o u t p u t = %h " , mon . mon_grants [ i ] ) ;

// c h e c k DUT and g o l d e n and r e c o r d


i f ( ( mon . mon_grants [ i ] == 1 ) & chk_golden_grant_weights
[ i ] == mon . mon_weight_array [ i ] )
begin
sb . r e c o r d ( i ) ;
end
else
begin
II-51

// i f t h e t e s t f a i l s , d i s p l a y some h e l p f u l
information
$ d i s p l a y ( " f a i l u r e ␣ a t ␣%g , ␣ i n d e x ␣%h , ␣ e x p e c t e d ␣ w e i g h t
␣=␣%h , ␣ a c t u a l ␣ w e i g h t ␣=␣%h " , $time , i ,
chk_golden_grant_weights [ i ] , mon .
mon_weight_array [ i ] ) ;
$finish ;

end

end
end

sb . d i s p l a y ( ) ;
// $ d i s p l a y ( " cov %e " , $ g e t _ c o v e r a g e ( ) ) ;

end
e n d t a s k : check_output

// u p d a t e g o l d e n t e s t v e c t o r s when d r i v e r i s done d r i v i n g
// i t i s a l w a y s r u n n i g − f o r e v e r
t a s k check : : update_golden_data ( ) ;
forever
begin
@( e_drv_done )
chk_golden_grants = a g t . g o l d e n _ g r a n t s ;
chk_golden_grant_weights = a g t . golden_grant_weights ;

// $ d i s p l a y ( " l o c a l g o l d e n g r a n t = %b " , c h k _ g o l d e n _ g r a n t s ) ;

f o r ( i n t i = 0 ; i < `CHANNELS; i ++)


begin
// $ d i s p l a y ( " l o c a l g o l d e n w e i g h t %d = %h " , i ,
chk_golden_grant_weights [ i ] ) ;
end
end
e n d t a s k : update_golden_data
II-52

Listing II.7: Scoreboard Module

// s c o r e b o a r d . s v
// s c o r e b o a r d c l a s s
// r e c o r d s t h e number o f h i t s

c l a s s scoreboard ;
i n t s c o r e _ a r r a y [`CHANNELS ] ;

// d e f a u l t c o n s t r u c t i o n
f u n c t i o n new ( ) ;
t h i s . score_array = '{ d e f a u l t : 0 } ;
e n d f u n c t i o n : new

// r e c o r d s c o r e
extern function void record ( i n t reqIndex ) ;

// d i s p l a y s c o r e
extern function void display ;
endclass : scoreboard

//−−−−−−−−−−E x t e r n a l Methods−−−−−−−−−−//
// r e c o r d f u n c t i o n
// u p d a t e t h e r e q u e s t o r c h a n n e l c o un t
function void scoreboard : : record ( i n t reqIndex ) ;
// i n c r e m e n t
score_array [ reqIndex ] = score_array [ reqIndex ] + 1;

endfunction : record

// d i s p l a y c u r r e n t s c o r e
function void scoreboard : : display ( ) ;
f o r ( i n t i = 0 ; i < `CHANNELS; i ++)
begin
$ d i s p l a y ( "CHANNEL␣%d␣ s c o r e ␣=␣%d " , i , s c o r e _ a r r a y [ i ] ) ;
end

endfunction : display
II-53

Listing II.8: Assertion Module

// a s s e r t i o n . s v
// This module d e f i n e s t h e a s s e r t i o n p r o p e r t i e s

module a s s e r t i o n ( i n t f _ r c c i n t f ) ;
// r e s e t s e q u e n c e
sequence reset_seq ;
( i n t f . r e s e t == 1 ) ##1 ( i n t f . g r a n t == 0 ) ;
endsequence

// r e s e t c o n d i t i o n
property reset_property ;
@( p o s e d g e i n t f . c l k )
( i n t f . r e s e t == 1 ) |−> r e s e t _ s e q ;
endproperty
endmodule
II-54

Listing II.9: Interface Module

// i n t e r f a c e . s v
// i n t e r f a c e module
// t h i s c l a s s d e c l a r e s and d e f i n e s i n t e r f a c e b e t w e e n various blocks

i n t e r f a c e intf_rrb ( input b it clk ) ;

bit reset ; // system r e s e t


b i t test_mode = 0 ; // DFT test_mode

b i t [`CHANNELS−1 : 0 ] r e q u e s t ; // r e q u e s t i n p u t t o RRB
l o g i c [`CHANNELS∗`WIDTH − 1 : 0 ] w e i g h t ; // w e i g h t i n p u t t o RRB

b i t [`CHANNELS−1 : 0 ] g r a n t ; // g r a n t o u t p u t from RRB

// modport f o r RRB module


modport RRB ( i n p u t r e s e t , c l k , r e q u e s t , weight ,
output g r a n t ) ;

// modport f o r d r i v e r c l a s s
modport DRIVER ( i n p u t c l k ,
output r e s e t , r e q u e s t , w e i g h t ) ;

// modport f o r monitor c l a s s
modport MONITOR ( i n p u t c l k , g r a n t ) ;

// r e s e t c o n d i t i o n a s s e r t
property reset_state ;
@( p o s e d g e c l k ) r e s e t |−> g r a n t ==0;

endproperty

resetAssert : a s s e r t property ( reset_state ) ;

endinterface
II-55

Listing II.10: Environment Module

// environment . s v
// environment c l a s s
// D e f i n e s a l l modules t o c r e a t e a t e s t environment

c l a s s environment ;

// s i n g l e r e q u e s t o r
requestor req ;

// c l a s s i n s t a n c e s
virtual intf_rrb i n t f ;
g e n e r a t o r gen ;
agent agt ;
d r i v e r drv ;
monitor mon ;
scoreboard scb ;
check chk ;

// e v e n t s
e v e n t e_drv_done ;
e v e n t e_mon_done ;

// d e f a u l t c o n s t r u c t o r
f u n c t i o n new ( v i r t u a l i n t f _ r r b i n t f ) ;
this . intf = intf ;

t h i s . r e q = new (`SEED , `WEIGHTLOW, `WEIGHTHIGH) ;

// i n t i a l i z e t r a n s a c t o r s
gen = new ( r e q ) ;
a g t = new ( gen ) ;
drv = new ( i n t f , agt , e_drv_done ) ;
mon = new ( i n t f , e_drv_done , e_mon_done ) ;
s c b = new ( ) ;
chk = new ( scb , agt , mon , e_mon_done , e_drv_done ) ;
e n d f u n c t i o n : new

e n d c l a s s : environment
II-56

Listing II.11: TopLevel Module

// t o p L e v e l . s v
// t o p l e v e l SV t e s t module f o r RRB

module t o p L e v e l ( ) ;

// t e s t M o d u l e s t e s t M o d u l e s ( ) ;
reg clk = 0;

// c l o c k g e n e r a t o r
initial
f o r e v e r #(`CLOCK_PERIOD/ 2 ) c l k = ~ c l k ;

// i n t e r f a c e i n s t a n c e
intf_rrb i n t f ( clk ) ;

// DUT
RRBTOP #(
.CHANNELS(`CHANNELS) ,
.WIDTH(`WIDTH) ,
. WEIGHTLIMIT(`WEIGHTLIMIT)
)
top (
. r e s e t ( i n t f .RRB. r e s e t ) ,
. c l k ( i n t f .RRB. c l k ) ,
. r e q u e s t ( i n t f .RRB. r e q u e s t ) ,
. w e i g h t ( i n t f .RRB. w e i g h t ) ,
. g r a n t ( i n t f .RRB. g r a n t )
);

// t e s t c a s e
testcase test ( intf ) ;

endmodule
II-57

Listing II.12: TestCase Module

// t e s t . s v
// t e s t c a s e f o r RoundRobin A r b i t e r

`include " i n c l u d e / RRB_verification . h"

program t e s t c a s e ( i n t f _ r r b i n t f ) ;
genvar i ;
// c o v e r a g e i n f o
c o v e r g r o u p din_cov@ ( p o s e d g e i n t f .RRB. c l k ) ;
r e q u e s t _ c o v e r a g e : c o v e r p o i n t i n t f .RRB. r e q u e s t ;
w e i g h t _ c o v e r a g e : c o v e r p o i n t i g n o r e F u n c t i o n ( i n t f .RRB. w e i g h t ) {
b i n s bin_1 = { 1 ' b1 } ;
}

// o p t i o n . p e r _ i n s t a n c e =1;
endgroup

// Function t o i g n o r e w e i g h t s l e s s than 3
integer n;
f u n c t i o n b i t i g n o r e F u n c t i o n ( l o g i c [`CHANNELS∗`WIDTH − 1 : 0 ]
weight ) ;

// $ d i s p l a y ( " w e i g h t = %h " , w e i g h t ) ;
f o r ( n = 0 ; n < `CHANNELS; n++)
begin
// $ d i s p l a y ( "N = %d " , n ) ;
// $ d i s p l a y ( "w c o v e r a g e t e s t : %h " , ( w e i g h t >> ( n∗`WIDTH) &
`WEIGHTMASK) ) ;
i f ( ( ( weight >>(n∗`WIDTH) ) & `WEIGHTMASK) <= 2 )
begin
// r e t u r n 0 ;
// $ d i s p l a y ( " r e t u r n i n g f a l s e " ) ;
end
end

// $ d i s p l a y ( " r e t u r n i n g t r u e " ) ;
return 1;
endfunction

c o v e r g r o u p dout_cov@ ( p o s e d g e i n t f .RRB. c l k ) ;
g r a n t _ c o v e r a g e : c o v e r p o i n t i n t f .RRB. g r a n t {
II-58

bins ch0 = {0};


bins ch1 = {1<<1};
bins ch2 = {1<<2};
bins ch3 = {1<<3};
bins ch4 = {1<<4};
bins ch5 = {1<<5};
bins ch6 = {1<<6};
bins ch7 = {1<<7};
}

o p t i o n . p e r _ i n s t a n c e =1;
endgroup

// c o v e r a g e h a n d l e
din_cov din_covergroup = new ( ) ;
dout_cov dout_covergroup = new ( ) ;

// env o b j e c t ( i n t e r f a c e )
environment env = new ( i n t f ) ;

initial
begin
$ t i m e f o r m a t ( −9 ,2 , " ns " , 1 6 ) ;
$set_coverage_db_name ( " t e s t C o v " ) ;

// s t a r t c o n v e r a g e c o l l e c t i o n
din_covergroup . s t a r t ( ) ;
dout_covergroup . s t a r t ( ) ;

// r e s e t d u t
env . drv . r e s e t ( ) ;

// Test s t a r t e d
$ d i s p l a y ( "−−−−−Test ␣ s t a r t e d −−−−−" ) ;

// g e n e r a t e new t e s t v e c t o r s
env . a g t . g e n e r a t e _ r e q u e s t s ( ) ;
$ d i s p l a y ( "−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−" ) ;

// run monitor , mon/ d r v e v e n t sync l o g i c


fork
env . mon . run ( ) ;
env . drv . e v e n t _ l o g i c ( ) ;
II-59

env . mon . e v e n t _ l o g i c ( ) ;
env . chk . update_golden_data ( ) ;
env . chk . check_output ( ) ;
join_none

fork
// env . chk . c h e c k _ o u t p u t ( ) ;
join_none

@( p o s e d g e i n t f . DRIVER . c l k ) ;
// d r i v e t h e t e s t v e c t o r , w a i t f o r sum ( r e q u e s t ∗ w e i g h t ) , and
generate again
f o r ( i n t i = 0 ; i < `NUM_ITERATIONS; i ++)
begin
$ d i s p l a y ( " i t e r a t i o n ␣=␣%d " , i ) ;
fork
// send t h e t e s t v e c t o r s t o DUT
env . drv . drive_new_data ( ) ;
join
// g e n e r a t e new t e s t v e c t o r s ( r e q u e s t s )
env . a g t . g e n e r a t e _ r e q u e s t s ( ) ;
$ d i s p l a y ( "−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−" ) ;
// $ d i s p l a y ("% g j o i n " , $time ) ;
end

@( p o s e d g e intf . DRIVER . c l k ) ;
@( p o s e d g e intf . DRIVER . c l k ) ;
@( p o s e d g e intf . DRIVER . c l k ) ;
@( p o s e d g e intf . DRIVER . c l k ) ;
@( p o s e d g e intf . DRIVER . c l k ) ;
@( p o s e d g e intf . DRIVER . c l k ) ;

end

final
begin
// d i s p l a y s c o r e b o a r d r e s u l t s
env . s c b . d i s p l a y ( ) ;

// d i s p l a y c o v e r a g e r e s u l t s
$ d i s p l a y ( " Input ␣ r e q u e s t ␣ c o v e r a g e ␣=␣%e " , din_covergroup .
II-60

request_coverage . get_coverage ( ) ) ;
$ d i s p l a y ( " Input ␣ w e i g h t ␣ c o v e r a g e ␣=␣%e " , din_covergroup .
weight_coverage . get_coverage ( ) ) ;
$ d i s p l a y ( " Output ␣ g r a n t ␣ c o v e r a g e ␣=␣%e " , dout_covergroup .
grant_coverage . get_coverage ( ) ) ;

end

endprogram : t e s t c a s e

You might also like