1use crate::{dff::DFF, dff_setup, fifo::async_fifo::AsynchronousFIFO, sdram::SDRAMDriver};
2use rust_hdl_core::prelude::*;
3
4use super::{burst_controller::SDRAMBurstController, timings::MemoryTimings, OutputBuffer};
5
6#[derive(Copy, Clone, Debug, PartialEq, LogicState)]
7enum State {
8 Idle,
9 Read,
10 Write,
11 Busy,
12}
13
14#[derive(LogicBlock)]
15pub struct SDRAMFIFOController<
16 const R: usize, const C: usize, const L: u32, const D: usize, const A: usize, > {
22 pub clock: Signal<In, Clock>,
23 pub sdram: SDRAMDriver<D>,
24 pub ram_clock: Signal<In, Clock>,
25 pub data_in: Signal<In, Bits<D>>,
27 pub write: Signal<In, Bit>,
28 pub full: Signal<Out, Bit>,
29 pub data_out: Signal<Out, Bits<D>>,
30 pub read: Signal<In, Bit>,
31 pub empty: Signal<Out, Bit>,
32 pub overflow: Signal<Out, Bit>,
33 pub underflow: Signal<Out, Bit>,
34 pub status: Signal<Out, Bits<8>>,
35 controller: SDRAMBurstController<R, C, L, D>,
36 fp: AsynchronousFIFO<Bits<D>, 5, 6, L>,
37 bp: AsynchronousFIFO<Bits<D>, 5, 6, L>,
38 can_write: DFF<Bit>,
39 can_read: DFF<Bit>,
40 read_pointer: DFF<Bits<A>>,
41 write_pointer: DFF<Bits<A>>,
42 dram_is_empty: DFF<Bit>,
43 dram_is_full: DFF<Bit>,
44 state: DFF<State>,
45 line_to_word_ratio: Constant<Bits<A>>,
46 fill: DFF<Bits<A>>,
47 fill_0: Constant<Bits<A>>,
48 fill_1: Constant<Bits<A>>,
49 fill_2: Constant<Bits<A>>,
50 fill_3: Constant<Bits<A>>,
51}
52
53impl<const R: usize, const C: usize, const L: u32, const D: usize, const A: usize>
54 SDRAMFIFOController<R, C, L, D, A>
55{
56 pub fn new(cas_delay: u32, timings: MemoryTimings, buffer: OutputBuffer) -> Self {
57 assert_eq!((1 << C) % L, 0);
58 assert_eq!(A, C + R + 2);
59 assert!(L < 32);
60 let banks = 4; let bit_count = R * C * D * banks;
63 let entry_bits = L as usize * D;
65 let max_entries = bit_count / entry_bits;
66 let entries_per_led = max_entries / 5;
68 Self {
69 clock: Default::default(),
70 sdram: Default::default(),
71 ram_clock: Default::default(),
72 data_in: Default::default(),
73 write: Default::default(),
74 full: Default::default(),
75 data_out: Default::default(),
76 read: Default::default(),
77 empty: Default::default(),
78 overflow: Default::default(),
79 underflow: Default::default(),
80 status: Default::default(),
81 controller: SDRAMBurstController::new(cas_delay, timings, buffer),
82 fp: Default::default(),
83 bp: Default::default(),
84 can_write: Default::default(),
85 can_read: Default::default(),
86 read_pointer: Default::default(),
87 write_pointer: Default::default(),
88 dram_is_empty: Default::default(),
89 dram_is_full: Default::default(),
90 state: Default::default(),
91 line_to_word_ratio: Constant::new(L.to_bits()),
92 fill: Default::default(),
93 fill_0: Constant::new((entries_per_led).to_bits()),
94 fill_1: Constant::new((entries_per_led * 2).to_bits()),
95 fill_2: Constant::new((entries_per_led * 3).to_bits()),
96 fill_3: Constant::new((entries_per_led * 4).to_bits()),
97 }
98 }
99}
100
101impl<const R: usize, const C: usize, const L: u32, const D: usize, const A: usize> Logic
102 for SDRAMFIFOController<R, C, L, D, A>
103{
104 #[hdl_gen]
105 fn update(&mut self) {
106 clock!(self, ram_clock, controller);
107 SDRAMDriver::<D>::link(&mut self.sdram, &mut self.controller.sdram);
108 dff_setup!(
109 self,
110 ram_clock,
111 read_pointer,
112 write_pointer,
113 dram_is_empty,
114 dram_is_full,
115 can_read,
116 can_write,
117 state,
118 fill
119 );
120 self.fp.write_clock.next = self.clock.val();
122 self.fp.read_clock.next = self.ram_clock.val();
123 self.bp.write_clock.next = self.ram_clock.val();
125 self.bp.read_clock.next = self.clock.val();
126 self.fp.data_in.next = self.data_in.val();
128 self.fp.write.next = self.write.val();
129 self.full.next = self.fp.full.val();
130 self.overflow.next = self.fp.overflow.val();
131 self.data_out.next = self.bp.data_out.val();
133 self.bp.read.next = self.read.val();
134 self.empty.next = self.bp.empty.val();
135 self.underflow.next = self.bp.underflow.val();
136 self.controller.data_in.next = self.fp.data_out.val();
140 self.fp.read.next = self.controller.data_strobe.val();
141 self.bp.data_in.next = self.controller.data_out.val();
143 self.bp.write.next = self.controller.data_valid.val();
144 self.dram_is_empty.d.next = self.read_pointer.q.val() == self.write_pointer.q.val();
147 self.dram_is_full.d.next = (self.write_pointer.q.val() + self.line_to_word_ratio.val())
148 == self.read_pointer.q.val();
149 self.can_write.d.next = !self.dram_is_full.q.val() & !self.fp.almost_empty.val();
150 self.can_read.d.next = !self.dram_is_empty.q.val() & !self.bp.almost_full.val();
151 self.controller.cmd_address.next = 0.into();
152 self.controller.write_not_read.next = false;
153 self.controller.cmd_strobe.next = false;
154 self.fill.clock.next = self.ram_clock.val();
155 self.fill.d.next = self.fill.q.val();
156 match self.state.q.val() {
157 State::Idle => {
158 if !self.controller.busy.val() {
159 if self.can_read.q.val() {
160 self.state.d.next = State::Read;
161 self.controller.cmd_address.next =
162 bit_cast::<32, A>(self.read_pointer.q.val());
163 self.controller.write_not_read.next = false;
164 self.controller.cmd_strobe.next = true;
165 } else if self.can_write.q.val() {
166 self.state.d.next = State::Write;
167 self.controller.cmd_address.next =
168 bit_cast::<32, A>(self.write_pointer.q.val());
169 self.controller.write_not_read.next = true;
170 self.controller.cmd_strobe.next = true;
171 }
172 }
173 }
174 State::Read => {
175 self.read_pointer.d.next =
176 self.read_pointer.q.val() + self.line_to_word_ratio.val();
177 self.fill.d.next = self.fill.q.val() - 1;
178 self.state.d.next = State::Busy;
179 }
180 State::Write => {
181 self.write_pointer.d.next =
182 self.write_pointer.q.val() + self.line_to_word_ratio.val();
183 self.fill.d.next = self.fill.q.val() + 1;
184 self.state.d.next = State::Busy;
185 }
186 State::Busy => {
187 if !self.controller.busy.val() {
188 self.state.d.next = State::Idle;
189 }
190 }
191 _ => {
192 self.state.d.next = State::Idle;
193 }
194 }
195 self.status.next = 0.into();
196 if self.fill.q.val() > self.fill_0.val() {
197 self.status.next = self.status.val() | 1;
198 }
199 if self.fill.q.val() > self.fill_1.val() {
200 self.status.next = self.status.val() | 2;
201 }
202 if self.fill.q.val() > self.fill_2.val() {
203 self.status.next = self.status.val() | 4;
204 }
205 if self.fill.q.val() > self.fill_3.val() {
206 self.status.next = self.status.val() | 8;
207 }
208 if self.underflow.val() | self.overflow.val() {
209 self.status.next = self.status.val() | 16;
210 }
211 if self.dram_is_empty.q.val() {
212 self.status.next = self.status.val() | 32;
213 }
214 if self.fp.empty.val() {
215 self.status.next = self.status.val() | 64;
216 }
217 if self.bp.full.val() {
218 self.status.next = self.status.val() | 128;
219 }
220 }
221}