-
Notifications
You must be signed in to change notification settings - Fork 1
/
CountUpDownSet.scala
144 lines (120 loc) · 4.14 KB
/
CountUpDownSet.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package MySpinalHardware
import spinal.core._
import spinal.lib._
object Pow2 {
def apply(value: BigInt): Int = {
if (value < 0) SpinalError(s"No negative value ($value) on ${this.getClass.getSimpleName}")
scala.math.pow(2, value.toDouble).toInt;
}
}
object CounterUpDownSet {
def apply(maxCount: BigInt): CounterUpDownSet = new CounterUpDownSet(maxCount)
def apply(maxCount: BigInt, incWhen: Bool, decWhen : Bool): CounterUpDownSet = {
val counter = CounterUpDownSet(maxCount)
when(incWhen) {
counter.increment()
}
when(decWhen) {
counter.decrement()
}
counter
}
// implicit def implicitValue(c: Counter) = c.value
}
class CounterUpDownSet(val maxCount: BigInt) extends ImplicitArea[UInt]
{
val incrementIt = False
val decrementIt = False
val setIt = False
val newValue = UInt(log2Up(maxCount) bit)
newValue := 0
def increment(): Unit = incrementIt := True
def decrement(): Unit = decrementIt := True
def setValue(value: UInt): Unit = {
newValue := value
setIt := True
}
def ===(that: UInt): Bool = this.value === that
def !==(that: UInt): Bool = this.value =/= that
def =/=(that: UInt): Bool = this.value =/= that
val valueNext = UInt(log2Up(maxCount) bit)
val value = RegNext(valueNext) init(0)
val willOverflowIfInc = value === maxCount - 1 && !decrementIt
val willOverflow = willOverflowIfInc && incrementIt
val finalIncrement = UInt(log2Up(maxCount) bit)
when(incrementIt && !decrementIt){
finalIncrement := 1
}elsewhen(!incrementIt && decrementIt){
finalIncrement := finalIncrement.maxValue
}otherwise{
finalIncrement := 0
}
when(setIt){
valueNext := newValue
}otherwise{
if (isPow2(maxCount)) {
valueNext := (value + finalIncrement).resized
} else {
assert(false,"CounterUpDownSet Need to be power of 2 and is: "+ maxCount)
}
}
override def implicitValue: UInt = value
}
object CounterSet {
def apply(start: BigInt,end: BigInt) : CounterSet = new CounterSet(start = start, end = end)
def apply(range : Range) : CounterSet = {
require(range.step == 1)
CounterSet(start = range.low, end = range.high)
}
def apply(maxCount: BigInt): CounterSet = new CounterSet(start = 0, end = maxCount-1)
def apply(bitCount: BitCount): CounterSet = new CounterSet(start = 0, end = (BigInt(1)<<bitCount.value)-1)
def apply(start: BigInt,end: BigInt, inc: Bool) : CounterSet = {
val counter = CounterSet(start,end)
when(inc) {
counter.increment()
}
counter
}
def apply(range : Range, inc: Bool) : CounterSet = {
require(range.step == 1)
CounterSet(start = range.low, end = range.high,inc = inc)
}
def apply(maxCount: BigInt, inc: Bool): CounterSet = CounterSet(start = 0, end = maxCount-1,inc = inc)
def apply(bitCount: BitCount, inc: Bool): CounterSet = CounterSet(start = 0, end = (BigInt(1)<<bitCount.value)-1,inc = inc)
}
// start and end inclusive, up counter
class CounterSet(val start: BigInt,val end: BigInt) extends ImplicitArea[UInt] {
require(start <= end)
val willIncrement = False.allowOverride
val willClear = False.allowOverride
val setValue = False
val newValue = UInt(log2Up(end + 1) bit)
def clear(): Unit = willClear := True
def increment(): Unit = willIncrement := True
newValue := 0
def setValue(value: UInt): Unit = {
newValue := value
setValue := True
}
val valueNext = UInt(log2Up(end + 1) bit)
val value = RegNext(valueNext) init(start)
val willOverflowIfInc = value === end
val willOverflow = willOverflowIfInc && willIncrement
if (isPow2(end + 1) && start == 0) { //Check if using overflow follow the spec
valueNext := (value + U(willIncrement)).resized
} else {
when(willOverflow){
valueNext := U(start)
} otherwise {
valueNext := (value + U(willIncrement)).resized
}
}
when(setValue) {
valueNext := newValue
}elsewhen(willClear) {
valueNext := start
}
willOverflowIfInc.allowPruning
willOverflow.allowPruning
override def implicitValue: UInt = this.value
}