-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathflash_loader_tb.cpp
139 lines (116 loc) · 3.37 KB
/
flash_loader_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
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdlib.h>
#include <verilated.h>
#include <verilated_vcd_c.h>
#include <Vflash_loader.h>
struct DummyFlash {
DummyFlash(uint8_t *mosi, uint8_t *miso, uint8_t *sck, uint8_t *cs)
: spi_mosi(mosi), spi_miso(miso), spi_sck(sck), spi_cs(cs) {}
uint8_t *spi_mosi;
uint8_t *spi_miso;
uint8_t *spi_sck;
uint8_t *spi_cs;
const char *data = "This is a test string";
const unsigned data_len = strlen(data);
// Current shift register output index
unsigned shift_bit_index = 0;
unsigned shift_byte_index = 0;
unsigned preamble_bit_count = 0;
// Last clock state
uint8_t last_sck = 0;
uint8_t last_cs = 0;
void eval() {
// Did the CS state change
if (*spi_cs != last_cs) {
fprintf(stderr, "CS state: was %u, now %u\n", last_cs, *spi_cs);
if (*spi_cs == 0) {
// Reset preamble counter so we don't respond during the read command
// setup
preamble_bit_count = 0;
shift_byte_index = 0;
shift_bit_index = 0;
*spi_miso = 1;
last_sck = *spi_sck;
} else {
// Deselect
*spi_miso = 1;
}
last_cs = *spi_cs;
}
// Are we currently selected?
if (last_cs == 1) {
// If no, just leave
return;
}
// Did the clock transition?
if (*spi_sck == last_sck) {
return;
}
// Update tracking var
last_sck = *spi_sck;
if (last_sck) {
// Posedge
preamble_bit_count++;
} else {
// Negedge
// Don't shift data if this is the read preamble
if (preamble_bit_count >= 40) {
// Set miso to be the next bit
*spi_miso =
data[shift_byte_index] & (0b1000'0000 >> shift_bit_index) ? 1 : 0;
// Increment the bit index
shift_bit_index++;
// If we hit the end of the byte, increment the byte index
if (shift_bit_index > 7) {
shift_bit_index = 0;
shift_byte_index++;
if (shift_byte_index >= data_len)
shift_byte_index = 0;
}
}
}
}
};
int main(int argc, char **argv) {
// Initialize Verilators variables
Verilated::commandArgs(argc, argv);
Verilated::traceEverOn(true);
// Create our trace output
VerilatedVcdC *vcd_trace = new VerilatedVcdC();
// Create an instance of our module under test
Vflash_loader *flash_loader = new Vflash_loader;
// Create our emulated flash chip on the SPI connections
DummyFlash dummy_flash(&flash_loader->o_flash_mosi,
&flash_loader->i_flash_miso,
&flash_loader->o_flash_sck, &flash_loader->o_flash_cs);
// Point the timer at the trace
flash_loader->trace(vcd_trace, 99);
vcd_trace->open("flash_loader.vcd");
uint64_t trace_tick = 0;
// Init to reset
flash_loader->i_clk = 0;
flash_loader->i_read_stb = 0;
for (unsigned i = 0; i < 150000; i++) {
// Negative edge
flash_loader->i_clk = 0;
flash_loader->eval();
dummy_flash.eval();
vcd_trace->dump(trace_tick++);
// Trigger read on clock 3;
if (trace_tick == 3) {
flash_loader->i_read_stb = 1;
} else {
flash_loader->i_read_stb = 0;
}
// Posedge
flash_loader->i_clk = 1;
flash_loader->eval();
dummy_flash.eval();
vcd_trace->dump(trace_tick++);
}
vcd_trace->flush();
vcd_trace->close();
exit(EXIT_SUCCESS);
}