1use crate::dff::DFF;
2use crate::dff_setup;
3use crate::prelude::DelayLine;
4use crate::sdram::cmd::{SDRAMCommand, SDRAMCommandEncoder};
5use crate::sdram::{OutputBuffer, SDRAMDriver};
6use rust_hdl_core::prelude::*;
7
8use super::timings::MemoryTimings;
9
10#[derive(Copy, Clone, PartialEq, Debug, LogicState)]
12enum State {
13 Boot,
14 Precharge1,
15 AutoRefresh1,
16 AutoRefresh2,
17 LoadModeRegister,
18 Idle,
19 IssueRead,
20 IssueWrite,
21 Refresh,
22 ReadActivate,
23 ReadCycle,
24 WriteActivate,
25 WritePrep,
26 WriteCycle,
27 Recovery,
28 Precharge,
29 Error,
30}
31
32#[derive(LogicBlock)]
41pub struct SDRAMBurstController<const R: usize, const C: usize, const L: u32, const D: usize> {
42 pub clock: Signal<In, Clock>,
43 pub sdram: SDRAMDriver<D>,
44 pub data_in: Signal<In, Bits<D>>,
49 pub data_strobe: Signal<Out, Bit>,
50 pub data_out: Signal<Out, Bits<D>>,
55 pub data_valid: Signal<Out, Bit>,
56 pub write_not_read: Signal<In, Bit>,
58 pub cmd_strobe: Signal<In, Bit>,
59 pub cmd_address: Signal<In, Bits<32>>,
60 pub busy: Signal<Out, Bit>,
61 pub error: Signal<Out, Bit>,
62 cmd: Signal<Local, SDRAMCommand>,
63 encode: SDRAMCommandEncoder,
64 boot_delay: Constant<Bits<16>>,
65 t_rp: Constant<Bits<16>>,
66 t_rfc: Constant<Bits<16>>,
67 t_refresh_max: Constant<Bits<16>>,
68 t_rcd: Constant<Bits<16>>,
69 t_wr: Constant<Bits<16>>,
70 max_transfer_size: Constant<Bits<6>>,
71 mode_register: Constant<Bits<13>>,
72 cas_delay: Constant<Bits<3>>,
73 state: DFF<State>,
74 reg_address: DFF<Bits<32>>,
75 reg_cmd_address: DFF<Bits<32>>,
76 delay_counter: DFF<Bits<16>>,
77 refresh_counter: DFF<Bits<16>>,
78 transfer_counter: DFF<Bits<6>>,
79 read_valid: DelayLine<Bit, 8, 3>,
80 addr_bank: Signal<Local, Bits<2>>,
81 addr_row: Signal<Local, Bits<13>>,
82 addr_col: Signal<Local, Bits<13>>,
83 write_pending: DFF<Bit>,
84 read_pending: DFF<Bit>,
85 refresh_needed: DFF<Bit>,
86 row_bits: Constant<Bits<32>>,
87 col_bits: Constant<Bits<32>>,
88 data_in_reg: DFF<Bits<D>>,
91 data_strobe_reg: DFF<Bit>,
92 data_out_reg: DFF<Bits<D>>,
93}
94
95impl<const R: usize, const C: usize, const L: u32, const D: usize>
96 SDRAMBurstController<R, C, L, D>
97{
98 pub fn new(
99 cas_delay: u32,
100 timings: MemoryTimings,
101 buffer: OutputBuffer,
102 ) -> SDRAMBurstController<R, C, L, D> {
103 assert!(L < 64);
104 assert_eq!((1 << C) % L, 0);
105 let mode_register = cas_delay << 4;
113 Self {
114 clock: Default::default(),
115 sdram: Default::default(),
116 cmd: Default::default(),
117 data_in: Default::default(),
118 data_strobe: Default::default(),
119 write_not_read: Default::default(),
120 cmd_strobe: Default::default(),
121 cmd_address: Default::default(),
122 busy: Default::default(),
123 data_out: Default::default(),
124 data_valid: Default::default(),
125 error: Default::default(),
126 boot_delay: Constant::new((timings.t_boot() + 50).to_bits()),
127 t_rp: Constant::new((timings.t_rp()).to_bits()),
128 t_rfc: Constant::new((timings.t_rfc()).to_bits()),
129 t_refresh_max: Constant::new((timings.t_refresh_max() * 7 / 10).to_bits()),
130 t_rcd: Constant::new((timings.t_rcd()).to_bits()),
131 t_wr: Constant::new((timings.t_wr()).to_bits()),
132 max_transfer_size: Constant::new(L.to_bits()),
133 mode_register: Constant::new(mode_register.to_bits()),
134 cas_delay: Constant::new(
140 match buffer {
141 OutputBuffer::Wired => cas_delay + 1,
142 OutputBuffer::DelayOne => cas_delay + 2,
143 OutputBuffer::DelayTwo => cas_delay + 3,
144 }
145 .to_bits(),
146 ),
147 state: Default::default(),
148 reg_address: Default::default(),
149 reg_cmd_address: Default::default(),
150 delay_counter: Default::default(),
151 refresh_counter: Default::default(),
152 transfer_counter: Default::default(),
153 read_valid: Default::default(),
154 addr_bank: Default::default(),
155 addr_row: Default::default(),
156 addr_col: Default::default(),
157 write_pending: Default::default(),
158 row_bits: Constant::new(R.to_bits()),
159 col_bits: Constant::new(C.to_bits()),
160 data_in_reg: Default::default(),
161 read_pending: Default::default(),
162 encode: Default::default(),
163 refresh_needed: Default::default(),
164 data_out_reg: Default::default(),
165 data_strobe_reg: Default::default(),
166 }
167 }
168}
169
170impl<const R: usize, const C: usize, const L: u32, const D: usize> Logic
171 for SDRAMBurstController<R, C, L, D>
172{
173 #[hdl_gen]
174 fn update(&mut self) {
175 dff_setup!(
177 self,
178 clock,
179 state,
180 reg_address,
181 reg_cmd_address,
182 delay_counter,
183 refresh_counter,
184 transfer_counter,
185 write_pending,
186 read_pending,
187 refresh_needed,
188 data_in_reg,
189 data_strobe_reg,
190 data_out_reg
191 );
192 clock!(self, clock, read_valid);
193 self.delay_counter.d.next = self.delay_counter.q.val() + 1;
195 self.refresh_counter.d.next = self.refresh_counter.q.val() + 1;
196 self.cmd.next = SDRAMCommand::NOP;
197 self.sdram.address.next = 0.into();
198 self.sdram.bank.next = 0.into();
199 self.data_out.next = self.data_out_reg.q.val();
201 self.data_out_reg.d.next = self.sdram.read_data.val();
202 self.data_valid.next = self.read_valid.data_out.val();
203 self.sdram.write_enable.next = false;
204 self.sdram.write_data.next = self.data_in_reg.q.val();
206 self.data_strobe.next = self.data_strobe_reg.q.val();
207 self.read_valid.data_in.next = false;
208 self.read_valid.delay.next = self.cas_delay.val();
209 self.addr_col.next = bit_cast::<13, C>(self.reg_address.q.val().get_bits::<C>(0));
211 self.addr_row.next = bit_cast::<13, R>(
212 self.reg_address
213 .q
214 .val()
215 .get_bits::<R>(self.col_bits.val().index()),
216 );
217 self.addr_bank.next = self
218 .reg_address
219 .q
220 .val()
221 .get_bits::<2>(self.col_bits.val().index() + self.row_bits.val().index());
222 self.transfer_counter.d.next = self.transfer_counter.q.val();
223 self.busy.next = (self.state.q.val() != State::Idle)
225 | self.write_pending.q.val()
226 | self.read_pending.q.val();
227 self.data_strobe_reg.d.next = false;
228 match self.state.q.val() {
229 State::Boot => {
230 if self.delay_counter.q.val() == self.boot_delay.val() {
231 self.state.d.next = State::Precharge1;
232 self.cmd.next = SDRAMCommand::Precharge;
233 self.sdram.address.next = 0xFFF.into();
234 self.delay_counter.d.next = 0.into();
235 }
236 }
237 State::Precharge1 => {
238 if self.delay_counter.q.val() == self.t_rp.val() {
239 self.state.d.next = State::AutoRefresh1;
240 self.cmd.next = SDRAMCommand::AutoRefresh;
241 self.delay_counter.d.next = 0.into();
242 }
243 }
244 State::AutoRefresh1 => {
245 if self.delay_counter.q.val() == self.t_rfc.val() {
246 self.state.d.next = State::AutoRefresh2;
247 self.cmd.next = SDRAMCommand::AutoRefresh;
248 self.delay_counter.d.next = 0.into();
249 }
250 }
251 State::AutoRefresh2 => {
252 if self.delay_counter.q.val() == self.t_rfc.val() {
253 self.state.d.next = State::LoadModeRegister;
254 self.cmd.next = SDRAMCommand::LoadModeRegister;
255 self.sdram.address.next = self.mode_register.val();
256 self.delay_counter.d.next = 0.into();
257 }
258 }
259 State::LoadModeRegister => {
260 if self.delay_counter.q.val() == 4 {
261 self.state.d.next = State::Idle;
262 }
263 }
264 State::Idle => {
265 self.delay_counter.d.next = 0.into();
266 self.transfer_counter.d.next = 0.into();
267 if self.refresh_needed.q.val() {
268 self.cmd.next = SDRAMCommand::AutoRefresh;
270 self.state.d.next = State::Refresh;
271 self.refresh_counter.d.next = 0.into();
272 self.refresh_needed.d.next = false;
273 } else if self.read_pending.q.val() {
274 self.reg_address.d.next = self.reg_cmd_address.q.val();
275 self.state.d.next = State::IssueRead;
276 } else if self.write_pending.q.val() {
277 self.reg_address.d.next = self.reg_cmd_address.q.val();
278 self.state.d.next = State::IssueWrite;
279 }
280 }
281 State::IssueRead => {
282 self.cmd.next = SDRAMCommand::Active;
283 self.sdram.bank.next = self.addr_bank.val();
284 self.sdram.address.next = self.addr_row.val();
285 self.state.d.next = State::ReadActivate;
286 self.read_pending.d.next = false;
287 }
288 State::IssueWrite => {
289 self.cmd.next = SDRAMCommand::Active;
290 self.sdram.bank.next = self.addr_bank.val();
291 self.sdram.address.next = self.addr_row.val();
292 self.state.d.next = State::WriteActivate;
293 self.write_pending.d.next = false;
294 self.sdram.write_enable.next = true;
295 }
296 State::Refresh => {
297 if self.delay_counter.q.val() == self.t_rfc.val() {
298 self.state.d.next = State::Idle;
299 }
300 }
301 State::ReadActivate => {
302 if self.delay_counter.q.val() == self.t_rcd.val() {
303 self.state.d.next = State::ReadCycle;
304 self.transfer_counter.d.next = 0.into();
305 }
306 }
307 State::WriteActivate => {
308 self.sdram.write_enable.next = true;
309 if self.delay_counter.q.val() == self.t_rcd.val() {
310 self.state.d.next = State::WritePrep;
311 self.transfer_counter.d.next = 0.into();
312 self.data_strobe_reg.d.next = true;
313 }
314 }
315 State::WritePrep => {
316 self.state.d.next = State::WriteCycle;
317 self.data_strobe_reg.d.next = true;
318 self.sdram.write_enable.next = true;
319 }
320 State::WriteCycle => {
321 self.sdram.write_enable.next = true;
322 if self.transfer_counter.q.val() < self.max_transfer_size.val() {
323 self.sdram.bank.next = self.addr_bank.val();
324 self.sdram.address.next = self.addr_col.val();
325 self.cmd.next = SDRAMCommand::Write;
326 self.transfer_counter.d.next = self.transfer_counter.q.val() + 1;
327 self.reg_address.d.next = self.reg_address.q.val() + 1;
328 } else {
329 self.delay_counter.d.next = 0.into();
330 self.state.d.next = State::Recovery;
331 }
332 if self.transfer_counter.q.val() < self.max_transfer_size.val() - 2 {
333 self.data_strobe_reg.d.next = true;
334 }
335 }
336 State::Recovery => {
337 self.sdram.write_enable.next = true;
338 if self.delay_counter.q.val() == self.t_wr.val() {
339 self.cmd.next = SDRAMCommand::Precharge;
340 self.sdram.address.next = 0x1FFF.into();
342 self.delay_counter.d.next = 0.into();
343 self.state.d.next = State::Precharge;
344 }
345 }
346 State::Precharge => {
347 if self.delay_counter.q.val() == self.t_rp.val() {
348 self.state.d.next = State::Idle;
349 }
350 }
351 State::ReadCycle => {
352 if self.transfer_counter.q.val() < self.max_transfer_size.val() {
353 self.sdram.bank.next = self.addr_bank.val();
354 self.sdram.address.next = self.addr_col.val();
355 self.cmd.next = SDRAMCommand::Read;
356 self.transfer_counter.d.next = self.transfer_counter.q.val() + 1;
357 self.read_valid.data_in.next = true;
358 self.reg_address.d.next = self.reg_address.q.val() + 1;
359 } else {
360 self.delay_counter.d.next = 0.into();
361 self.state.d.next = State::Recovery;
362 }
363 }
364 State::Error => {}
365 _ => {
366 self.state.d.next = State::Boot;
367 }
368 }
369 self.error.next = self.state.q.val() == State::Error;
370 if self.cmd_strobe.val() & !self.read_pending.q.val() & !self.write_pending.q.val() {
372 self.reg_cmd_address.d.next = self.cmd_address.val();
373 if self.write_not_read.val() {
374 self.write_pending.d.next = true;
375 } else {
376 self.read_pending.d.next = true;
377 }
378 }
379 if self.refresh_counter.q.val() >= self.t_refresh_max.val() {
380 self.refresh_needed.d.next = true;
381 }
382 self.sdram.cs_not.next = self.encode.cs_not.val();
384 self.sdram.cas_not.next = self.encode.cas_not.val();
385 self.sdram.ras_not.next = self.encode.ras_not.val();
386 self.sdram.we_not.next = self.encode.we_not.val();
387 self.encode.cmd.next = self.cmd.val();
388 self.sdram.clk.next = self.clock.val();
389 self.data_in_reg.d.next = self.data_in.val();
390 }
391}