This repository has been archived by the owner on Oct 23, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
spifr_blackbox.cc
94 lines (78 loc) · 2.3 KB
/
spifr_blackbox.cc
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
#include "build/sh1107.h"
#include <iostream>
/**
* Yawonk.
*/
extern "C" const uint8_t *spi_flash_content;
extern "C" uint32_t spi_flash_base;
extern "C" uint32_t spi_flash_length;
namespace cxxrtl_design {
struct bb_p_spifr_impl : public bb_p_spifr {
// Similar to bb_p_i2c_impl::TICKS_TO_WAIT, but between each cycle with valid
// data.
const uint8_t COUNTDOWN_BETWEEN_BYTES = 2u;
enum {
STATE_IDLE,
STATE_READ,
} state;
uint32_t address;
uint16_t remaining;
uint8_t countdown;
void reset() override {
this->state = STATE_IDLE;
this->address = 0u;
this->remaining = 0u;
this->countdown = 0u;
p_busy = wire<1>{0u};
p_data = wire<8>{0u};
p_valid = wire<1>{0u};
}
bool eval(performer *performer) override {
bool converged = true;
bool posedge_p_clk = this->posedge_p_clk();
if (posedge_p_clk) {
p_valid.next = value<1>{0u};
switch (this->state) {
case STATE_IDLE: {
if (p_stb) {
this->address = p_addr.get<uint32_t>();
this->remaining = p_len.get<uint16_t>();
if (this->address >= spi_flash_base &&
this->address < spi_flash_base + spi_flash_length) {
p_busy.next = value<1>{1u};
this->state = STATE_READ;
this->countdown = COUNTDOWN_BETWEEN_BYTES;
}
}
break;
}
case STATE_READ: {
if (--this->countdown == 0u) {
if (this->remaining == 0u) {
p_busy.next = value<1>{0u};
this->state = STATE_IDLE;
} else {
this->countdown = COUNTDOWN_BETWEEN_BYTES;
if (this->address - spi_flash_base < spi_flash_length)
p_data.next =
value<8>{spi_flash_content[this->address - spi_flash_base]};
else
p_data.next = value<8>{0xffu};
p_valid.next = value<1>{1u};
++this->address;
--this->remaining;
}
}
break;
}
}
}
return converged;
}
};
std::unique_ptr<bb_p_spifr> bb_p_spifr::create(std::string name,
metadata_map parameters,
metadata_map attributes) {
return std::make_unique<bb_p_spifr_impl>();
}
} // namespace cxxrtl_design