-
Notifications
You must be signed in to change notification settings - Fork 1
/
floppy_tb.cpp
228 lines (177 loc) · 4.27 KB
/
floppy_tb.cpp
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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
#include "Vfloppy.h"
#include "verilated.h"
#include "verilated_vcd_c.h"
#define SPINTEST 0 // test disk spinning up and down
#define STEPTEST 1 // test head stepping
#if SPINTEST
#define DUMP 10
#else
#define DUMP 1
#endif
Vfloppy* top = NULL;
#if DUMP
VerilatedVcdC* tfp = NULL;
#endif
double time_ns = 0;
int dump_enable = 0;
#define MHZ2NS(a) (1000000000.0/(a))
#define CLK (8000000.0)
void hexdump(void *data, int size) {
int i, b2c, n=0;
char *ptr = (char*)data;
if(!size) return;
while(size>0) {
printf(" %04x: ", n);
b2c = (size>16)?16:size;
for(i=0;i<b2c;i++) printf("%02x ", 0xff&ptr[i]);
printf(" ");
for(i=0;i<(16-b2c);i++) printf(" ");
for(i=0;i<b2c;i++) printf("%c", isprint(ptr[i])?ptr[i]:'.');
printf("\n");
ptr += b2c;
size -= b2c;
n += b2c;
}
}
void eval(void) {
static int last_clk = 0;
// evaluate recent changes
top->eval();
#if DUMP
if(dump_enable) {
static int dump_cnt = 0;
dump_cnt++;
if(dump_cnt >= DUMP) {
tfp->dump(time_ns);
dump_cnt = 0;
}
}
#endif
// eval on negedge of clk
if(!top->clk && last_clk) {
// ...
}
last_clk = top->clk;
}
// advance time and create valid 8 Mhz clock and signals
// derived from it
void wait_ns(double n) {
static double clk_time = 0;
eval();
// check if next clk event is within waiting period
while(clk_time <= n) {
time_ns += clk_time; // advance time to next clk event
n -= clk_time; // reduce remainung waiting time
// process change on clk
top->clk = !top->clk;
// check if floppy index changed
{ static int last_index = 0;
static double last_index_time = 0;
if(top->index != last_index) {
if(last_index_time > 0.001) {
double ev_time = (time_ns - last_index_time)/1000000;
if(!top->index) printf("RPM = %.3f\n", 60000/ev_time);
else printf("Index pulse len = %.3fms\n", ev_time);
}
// index starts on falling edge
if(!top->index) last_index_time = time_ns;
last_index = top->index;
}
}
{ static int motor_on=0;
static int rate=0;
static double motor_on_time = 0;
static double motor_off_time = 0;
if(!motor_on && top->motor_on) {
printf("motor on at %.3f RPM\n",
300.0*top->floppy__DOT__rate/250000.0);
motor_on_time = time_ns;
}
if(motor_on && !top->motor_on) {
printf("motor off at %.3f RPM\n",
300.0*top->floppy__DOT__rate/250000.0);
motor_off_time = time_ns;
}
motor_on = top->motor_on;
if((top->floppy__DOT__rate == 250000)&&(rate != 250000)) {
printf("Full RPM reached %.3fms after motor on\n",
(time_ns-motor_on_time)/1000000);
}
if((top->floppy__DOT__rate == 0)&&(rate != 0)) {
printf("Disk stopped %.3fms after motor off\n",
(time_ns-motor_off_time)/1000000);
}
rate = top->floppy__DOT__rate;
}
// things supposed to happen on rising clock edge
if(top->clk) {
}
eval();
clk_time = MHZ2NS(CLK)/2.0; // next clk change in 62.5ns
}
// next event is when done waiting
time_ns += n; // advance time
clk_time -= n;
}
void wait_us(double n) {
wait_ns(n * 1000.0);
}
void wait_ms(double n) {
wait_us(n * 1000.0);
}
int main(int argc, char **argv, char **env) {
Verilated::commandArgs(argc, argv);
// init top verilog instance
top = new Vfloppy;
int i;
#if DUMP
// init trace dump
Verilated::traceEverOn(true);
tfp = new VerilatedVcdC;
top->trace (tfp, 99);
tfp->open ("floppy.vcd");
#endif
// initialize system inputs
top->clk = 1;
top->motor_on = 0;
top->step_in = 0;
top->step_out = 0;
top->select = 0;
#if SPINTEST
dump_enable = 1;
// select after 1 ms
wait_ms(1);
top->select = 1;
// start motor after 5 ms
wait_ms(5);
top->motor_on = 1;
wait_ms(5*250);
top->motor_on = 0;
wait_ms(100);
top->motor_on = 1;
wait_ms(300);
top->motor_on = 0;
wait_ms(400);
#elif STEPTEST
// start disk quietly
top->motor_on = 1;
top->select = 1;
wait_ms(795);
dump_enable = 1;
wait_ms(10);
for(i=0;i<5;i++) {
// step signal
top->step_out = 1;
wait_ms(1);
top->step_out = 0;
wait_ms(2);
}
wait_ms(215);
// wait_ms(215);
#else
#endif
#if DUMP
tfp->close();
#endif
exit(0);
}