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
use crate::core::prelude::*;
use crate::hls::bus::{FIFOReadController, FIFOWriteController, SoCBusController};
use crate::widgets::prelude::*;
#[derive(LogicState, Debug, Copy, Clone, PartialEq)]
enum BaseControllerState {
    Idle,
    Ping,
    ReadLoadCount,
    Read,
    Write,
    WriteLoadCount,
    PollWait,
    Poll,
    StreamWait,
    Stream,
}
#[derive(LogicBlock, Default)]
pub struct BaseController<const A: usize> {
    pub from_cpu: FIFOReadController<Bits<16>>, pub to_cpu: FIFOWriteController<Bits<16>>,  pub clock: Signal<In, Clock>,               state: DFF<BaseControllerState>,
    pub bus: SoCBusController<16, { A }>,
    counter: DFF<Bits<16>>,
    opcode: Signal<Local, Bits<8>>,
}
impl<const A: usize> Logic for BaseController<A> {
    #[hdl_gen]
    fn update(&mut self) {
        dff_setup!(self, clock, state, counter);
        self.opcode.next = self.from_cpu.data.val().get_bits::<8>(8);
        self.from_cpu.read.next = false;
        self.to_cpu.data.next = 0.into();
        self.to_cpu.write.next = false;
        self.bus.clock.next = self.clock.val();
        self.bus.from_controller.next = 0.into();
        self.bus.strobe.next = false;
        self.bus.address.next = 0.into();
        self.bus.address_strobe.next = false;
        match self.state.q.val() {
            BaseControllerState::Idle => {
                if !self.from_cpu.empty.val() {
                    if self.opcode.val() == 0 {
                        self.from_cpu.read.next = true;
                    } else if self.opcode.val() == 1 {
                        self.state.d.next = BaseControllerState::Ping;
                    } else if self.opcode.val() == 2 {
                        self.bus.address.next = self.from_cpu.data.val().get_bits::<A>(0);
                        self.bus.address_strobe.next = true;
                        self.from_cpu.read.next = true;
                        self.state.d.next = BaseControllerState::ReadLoadCount;
                    } else if self.opcode.val() == 3 {
                        self.bus.address.next = self.from_cpu.data.val().get_bits::<A>(0);
                        self.bus.address_strobe.next = true;
                        self.from_cpu.read.next = true;
                        self.state.d.next = BaseControllerState::WriteLoadCount;
                    } else if self.opcode.val() == 4 {
                        self.bus.address.next = self.from_cpu.data.val().get_bits::<A>(0);
                        self.bus.address_strobe.next = true;
                        self.from_cpu.read.next = true;
                        self.state.d.next = BaseControllerState::PollWait;
                    } else if self.opcode.val() == 5 {
                        self.bus.address.next = self.from_cpu.data.val().get_bits::<A>(0);
                        self.bus.address_strobe.next = true;
                        self.from_cpu.read.next = true;
                        self.state.d.next = BaseControllerState::StreamWait;
                    }
                }
            }
            BaseControllerState::Ping => {
                self.to_cpu.data.next = self.from_cpu.data.val();
                self.to_cpu.write.next = true;
                self.from_cpu.read.next = true;
                self.state.d.next = BaseControllerState::Idle;
            }
            BaseControllerState::ReadLoadCount => {
                if !self.from_cpu.empty.val() {
                    self.counter.d.next = self.from_cpu.data.val();
                    self.from_cpu.read.next = true;
                    self.state.d.next = BaseControllerState::Read;
                }
            }
            BaseControllerState::Read => {
                if self.bus.ready.val() & !self.to_cpu.full.val() {
                    self.to_cpu.data.next = self.bus.to_controller.val();
                    self.bus.strobe.next = true;
                    self.to_cpu.write.next = true;
                    self.counter.d.next = self.counter.q.val() - 1;
                    if self.counter.q.val() == 1 {
                        self.state.d.next = BaseControllerState::Idle;
                    }
                }
            }
            BaseControllerState::WriteLoadCount => {
                if !self.from_cpu.empty.val() {
                    self.counter.d.next = self.from_cpu.data.val();
                    self.from_cpu.read.next = true;
                    self.state.d.next = BaseControllerState::Write;
                }
            }
            BaseControllerState::Write => {
                if self.bus.ready.val() & !self.from_cpu.empty.val() {
                    self.bus.from_controller.next = self.from_cpu.data.val();
                    self.bus.strobe.next = true;
                    self.from_cpu.read.next = true;
                    self.counter.d.next = self.counter.q.val() - 1;
                    if self.counter.q.val() == 1 {
                        self.state.d.next = BaseControllerState::Idle;
                    }
                }
            }
            BaseControllerState::PollWait => {
                self.state.d.next = BaseControllerState::Poll;
            }
            BaseControllerState::Poll => {
                if !self.to_cpu.full.val() {
                    self.to_cpu.data.next =
                        bits::<16>(0xFF00) | bit_cast::<16, 1>(self.bus.ready.val().into());
                    self.to_cpu.write.next = true;
                    self.state.d.next = BaseControllerState::Idle;
                }
            }
            BaseControllerState::StreamWait => {
                self.state.d.next = BaseControllerState::Stream;
            }
            BaseControllerState::Stream => {
                if self.bus.ready.val() & !self.to_cpu.full.val() {
                    self.to_cpu.data.next = self.bus.to_controller.val();
                    self.bus.strobe.next = true;
                    self.to_cpu.write.next = true;
                }
                if !self.from_cpu.empty.val() {
                    if self.from_cpu.data.val().any() {
                        self.state.d.next = BaseControllerState::Idle;
                    }
                    self.from_cpu.read.next = true;
                }
            }
            _ => {
                self.state.d.next = BaseControllerState::Idle;
            }
        }
    }
}
#[test]
fn test_base_controller_is_synthesizable() {
    let mut uut = BaseController::<4>::default();
    uut.connect_all();
    let vlog = generate_verilog(&uut);
    yosys_validate("base_controller", &vlog).unwrap();
}