1use rhdl::prelude::*;
12
13use crate::ports::{AxiWrite, AxiWriteResp, idle_write};
14
15#[derive(Clone, Copy, Debug, PartialEq, Digital, Default)]
17pub struct WriteReq {
18 pub start: bool,
20 pub base: b64,
22 pub word: b32,
24 pub values: [b32; 4],
26 pub count: b3,
28}
29
30#[kernel]
32pub fn idle_write_req() -> WriteReq {
33 WriteReq { start: false, base: b64(0), word: b32(0), values: [b32(0); 4], count: b3(0) }
34}
35
36#[derive(Clone, Copy, Debug, PartialEq, Digital, Default)]
38pub struct WriteIn {
39 pub req: WriteReq,
41 pub axi: AxiWriteResp,
43}
44
45#[derive(Clone, Copy, Debug, PartialEq, Digital, Default)]
47pub struct WriteOut {
48 pub busy: bool,
50 pub done: bool,
52 pub axi: AxiWrite,
54}
55
56#[derive(Clone, Copy, Debug, PartialEq, Digital, Default)]
58pub struct WriteState {
59 pub phase: b2,
61 pub addr: b64,
63 pub data: [b64; 8],
65 pub strb: b64,
67 pub req: WriteReq,
69 pub done_words: b3,
71 pub aw_done: bool,
73 pub w_done: bool,
75}
76
77#[derive(Clone, Debug, Synchronous, SynchronousDQ)]
79pub struct Writer {
80 state: rhdl_fpga::core::dff::DFF<WriteState>,
81}
82
83impl Default for Writer {
84 fn default() -> Self {
85 Self { state: rhdl_fpga::core::dff::DFF::new(WriteState::default()) }
86 }
87}
88
89impl SynchronousIO for Writer {
90 type I = WriteIn;
91 type O = WriteOut;
92 type Kernel = write_kernel;
93}
94
95#[kernel]
97pub fn write_kernel(_cr: ClockReset, i: WriteIn, q: WriterQ) -> (WriteOut, WriterD) {
98 let r = q.state;
99 let mut s = r;
100 let mut o = WriteOut { busy: false, done: false, axi: idle_write() };
101 o.busy = r.phase != b2(0);
102 if r.phase == b2(0) && i.req.start {
103 s.req = i.req;
104 s.done_words = b3(0);
105 s.phase = b2(3);
106 }
107 if r.phase == b2(3) {
109 let word = r.req.word + r.done_words.resize::<32>();
110 let mut value = r.req.values[0];
111 for k in 0..4 {
112 if r.done_words == b3(k as u128) {
113 value = r.req.values[k];
114 }
115 }
116 let byte = r.req.base + (word.resize::<64>() << b64(2));
117 let pos: b4 = (byte >> b64(2)).resize();
118 s.addr = byte & !b64(63);
119 s.strb = b64(0xf) << (pos.resize::<64>() << b64(2));
120 let mut d = [b64(0); 8];
121 for k in 0..8 {
122 if (pos >> b4(1)) == b4(k as u128) {
123 d[k] = if (pos & b4(1)) == b4(1) { value.resize::<64>() << b64(32) } else { value.resize::<64>() };
124 }
125 }
126 s.data = d;
127 s.aw_done = false;
128 s.w_done = false;
129 s.phase = b2(1);
130 }
131 if r.phase == b2(1) {
132 o.axi.aw_valid = !r.aw_done;
133 o.axi.aw_addr = r.addr;
134 o.axi.w_valid = !r.w_done;
135 o.axi.w_data = r.data;
136 o.axi.w_strb = r.strb;
137 let aw = r.aw_done || i.axi.aw_ready;
138 let w = r.w_done || i.axi.w_ready;
139 s.aw_done = aw;
140 s.w_done = w;
141 if aw && w {
142 s.phase = b2(2);
143 }
144 }
145 if r.phase == b2(2) {
146 o.axi.b_ready = true;
147 if i.axi.b_valid {
148 s.done_words = r.done_words + b3(1);
149 if r.done_words + b3(1) == r.req.count {
150 o.done = true;
151 s.phase = b2(0);
152 } else {
153 s.phase = b2(3);
154 }
155 }
156 }
157 (o, WriterD { state: s })
158}