-
Notifications
You must be signed in to change notification settings - Fork 1
/
Si5351.scala
161 lines (138 loc) · 3.87 KB
/
Si5351.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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
package MySpinalHardware
import spinal.core._
import spinal.lib._
import spinal.lib.fsm._
import spinal.core.sim._
class Si5351(File: String) extends Component{
val io = new Bundle {
val o_scl_write = out Bool()
val o_sda_write = out Bool()
val i_scl = in Bool()
val i_sda = in Bool()
val i_skip = in Bool()
val i_prog = in Bool()
val o_done = out Bool()
val o_error = out Bool()
}
val romAddr = Reg(UInt(8 bits)) init(0)
val configRom = new RamInit(File, log2Up(0xFF))
configRom.io.dina := 0
configRom.io.ena := True
configRom.io.wea := 0
configRom.io.addra := romAddr.asBits
val deviceAddr = B"7'h60"
val dataIn = Reg(Bits(8 bits)) init(0)
val i2c = new i2cMaster();
i2c.io.i_addr := deviceAddr
i2c.io.i_data := dataIn
i2c.io.i_scl := io.i_scl
i2c.io.i_sda := io.i_sda
io.o_scl_write := i2c.io.o_scl_write
io.o_sda_write := i2c.io.o_sda_write
io.o_error := i2c.io.o_error
i2c.io.i_read := False
i2c.io.i_send := False
i2c.io.i_end := False
i2c.io.i_stop := False
io.o_done := False;
val fsm = new StateMachine
{
val Init: State = new State with EntryPoint
{
whenIsActive{
romAddr := 0
dataIn := romAddr.asBits
when(io.i_skip){
goto(Done)
}otherwise{
i2c.io.i_send := True
goto(LoadConfiguration)
}
}
}
val LoadConfiguration: State = new State
{
whenIsActive{
when(i2c.io.o_sent){
dataIn := configRom.io.douta
when(romAddr === 0xE8){
i2c.io.i_end := True
goto(Done)
}otherwise{
goto(SendNext)
}
}
}
}
val SendNext: State = new State
{
whenIsActive{
when(!i2c.io.o_sent){
when(romAddr === 0xE8){
goto(Done)
}otherwise{
romAddr := romAddr + 1
goto(LoadConfiguration)
}
}
}
}
val Done: State = new State
{
whenIsActive{
i2c.io.i_end := True
io.o_done := True
when(io.i_prog){
goto(Init)
}
}
}
}
}
object Si5351_Sim {
def main(args: Array[String]) {
SimConfig.withFstWave.compile{
val dut = new Si5351("./data/si5351.bin")
dut
}.doSim{dut =>
//Fork a process to generate the reset and the clock on the dut
var modelState = 0
var addr = 0x00
var data = 0x00
var bitcounter = 0
var scl = true
var sda = true
var last_scl = true
var last_sda = true
dut.io.i_sda #= true
dut.io.i_scl #= true
dut.io.i_skip #= false
dut.clockDomain.forkStimulus(period = 10)
for(idx <- 0 to 30000){
scl = dut.io.o_scl_write.toBoolean
sda = dut.io.o_sda_write.toBoolean
if(!scl && last_scl && idx > 3){
if(bitcounter<9){
bitcounter=bitcounter+1
}else{
bitcounter=1
}
}
if(idx > 21175 && idx <= 21275){
dut.clockDomain.assertReset()
}else{
dut.clockDomain.deassertReset()
}
if(bitcounter==9){
dut.io.i_sda #= false
}else{
dut.io.i_sda #= true
}
last_scl = scl
last_sda = sda
//Wait a rising edge on the clock
dut.clockDomain.waitRisingEdge()
}
}
}
}