x393  1.0
FPGAcodeforElphelNC393camera
ahci_dma_rd_fifo.v
Go to the documentation of this file.
1 
41 `timescale 1ns/1ps
42 
44  parameter WCNT_BITS = 21,
45  parameter ADDRESS_BITS = 3
46 )(
47  input mrst,
48  input hrst,
49  input mclk,
50  input hclk,
51  // hclk domain
52  input [WCNT_BITS-1:0] wcnt, // decrementing word counter, 0- based (0 need 1, 1 - need 2, ...) valid @ start
53  input [1:0] woffs, // 2 LSBs of the initial word address - valid @ start
54  input start, // start transfer
55  input [63:0] din,
56  input din_av,
57  input din_av_many,
58  input last_prd, // last prd, flush partial dword if there were odd number of words transferred. valid @ start
59  // Or maybe use "last_prd"?
60  output din_re,
61  output reg done, // this PRD data sent to cross-clock FIFO (may result in only half-dword sent out),
62  // OK to fetch another PRD (if it was not the last)
63  output done_flush, // finished last PRD (indicated by last_prd @ start), data left module
64  // mclk domain
65  output [31:0] dout,
66  output dout_vld,
67  input dout_re,
68  output last_DW // dout contains last DW
69  ,output [31:0] debug_dma_h2d
70 
71 );
72  localparam ADDRESS_NUM = (1<<ADDRESS_BITS); // 8 for ADDRESS_BITS==3
73  reg [ADDRESS_BITS : 0] waddr; // 1 extra bit
74 // reg [ADDRESS_BITS+1:0] raddr; // 1 extra bit
75  reg [ADDRESS_BITS+1:0] raddr_r; // 1 extra bit
76  wire [ADDRESS_BITS+1:0] raddr_w; // 1 extra bit
77  reg [63:16] din_prev; // only 48 bits are needed
78  reg [WCNT_BITS-3:0] qwcntr;
79  reg busy;
80  wire [2:0] end_offs = wcnt[1:0] + woffs;
81 
82  reg [63:0] fifo_ram [0: ADDRESS_NUM - 1];
83  reg [3:0] vld_ram [0: ADDRESS_NUM - 1];
84  reg [(1<<ADDRESS_BITS)-1:0] fifo_full; // set in write clock domain
85  reg [(1<<ADDRESS_BITS)-1:0] fifo_nempty;// set in read clock domain
86  wire fifo_wr;
87  wire fifo_rd;
88  reg [1:0] fifo_rd_r;
89  reg mrst_hclk;
90 
91  wire [(1<<ADDRESS_BITS)-1:0] fifo_full2 = {~fifo_full[0],fifo_full[ADDRESS_NUM-1:1]};
92  reg fifo_dav; // @mclk
93  wire fifo_dav2_w;
94  reg fifo_dav2; // @mclk
95 
96  reg fifo_half_hclk; // Half Fifo is empty, OK to write
97  reg [1:0] woffs_r;
98 
99  wire [63:0] fifo_di= woffs_r[1]?(woffs_r[0] ? {din[47:0],din_prev[63:48]} : {din[31:0],din_prev[63:32]}):
100  (woffs_r[0] ? {din[15:0],din_prev[63:16]} : din[63:0]);
101  wire [3:0] fifo_di_vld;
102 // wire [63:0] fifo_do = fifo_ram [raddr[ADDRESS_BITS:1]];
103 // wire [3:0] fifo_do_vld = vld_ram [raddr[ADDRESS_BITS:1]];
104  reg [63:0] fifo_do_r;
105  reg [3:0] fifo_do_vld_r;
108  reg [3:0] last_mask;
110  reg flushing_hclk; // flushing data, ends when confirmed from mclk domain
111  reg flushing_mclk; // just registered flushing_hclk @mclk
112 
114 
115  assign din_re = busy && fifo_half_hclk && din_av_safe_r;
116  assign fifo_wr = en_fifo_wr && fifo_half_hclk && (din_av_safe_r || !busy);
117  assign fifo_di_vld = last_fifo_wr? last_mask : 4'hf;
118 
119 
120  wire [2:0] debug_waddr = waddr[2:0];
121  wire [2:0] debug_raddr = raddr_r[3:1];
122  // just for gtkwave - same names
123  wire [ADDRESS_BITS+1:0] raddr = raddr_r;
124  wire [63:0] fifo_do = fifo_do_r;
126 
127 
128 // assign fifo_dav2_w = fifo_full2[raddr[ADDRESS_BITS:1]] ^ raddr[ADDRESS_BITS+1];
129 /// assign fifo_dav2_w = fifo_full2[raddr_r[ADDRESS_BITS:1]] ^ raddr_r[ADDRESS_BITS+1];
131 
132 
133 
134  assign last_fifo_wr = !busy || ((qwcntr == 0) && ((woffs == 0) || end_offs[2])); // ((qwcntr != 0) || ((woffs != 0) && last_prd));
135 
136 
137  always @ (posedge hclk) begin
138  if (hrst) mrst_hclk <= 0;
139  else mrst_hclk <= mrst;
140 
141  if (mrst_hclk) busy <= 0;
142  else if (start) busy <= 1;
143  else if (din_re && (qwcntr == 0)) busy <= 0;
144 
145  done <= busy && din_re && (qwcntr == 0);
146 
147  if (mrst_hclk) en_fifo_wr <= 0;
148  else if (start) en_fifo_wr <= (woffs == 0);
149  else if (din_re || fifo_wr) en_fifo_wr <= busy && ((qwcntr != 0) || ((woffs != 0) && !end_offs[2]));
150 
151  if (start) qwcntr <= wcnt[WCNT_BITS-1:2] + end_offs[2];
152  else if (din_re) qwcntr <= qwcntr - 1;
153 
154 
155  if (start) woffs_r <= woffs;
156 
157  if (mrst_hclk) fifo_full <= 0;
159 
160  if (mrst_hclk) waddr <= 0;
161  else if (fifo_wr) waddr <= waddr+1;
162 
164 
165  if (din_re) din_prev[63:16] <= din[63:16];
166 
167  if (fifo_wr) fifo_ram[waddr[ADDRESS_BITS-1:0]] <= fifo_di;
169 // if (fifo_wr) flush_ram[waddr[ADDRESS_BITS-1:0]] <= fifo_di_flush;
170 
171  if (mrst_hclk) din_av_safe_r <= 0;
172  else din_av_safe_r <= din_av && (din_av_many || !din_re);
173 
174  if (start) last_mask <= {&wcnt[1:0], wcnt[1], |wcnt[1:0], 1'b1};
175 
176  if (mrst_hclk || done_flush) flushing_hclk <= 0;
177  else if (fifo_wr && last_prd && (((qwcntr == 0) && ((woffs == 0) || !last_prd)) || !busy)) flushing_hclk <= 1;
178 
179  end
180 
181  assign raddr_w = mrst ? 0 : (raddr_r + fifo_rd);
182 
183  always @ (posedge mclk) begin
184 
185  fifo_rd_r <= {fifo_rd_r[0],fifo_rd};
186 // if (mrst) raddr <= 0;
187 // else if (fifo_rd) raddr <= raddr + 1;
188 
189  raddr_r <= raddr_w;
190 
191  if (mrst) fifo_nempty <= {{(ADDRESS_NUM>>1){1'b0}},{(ADDRESS_NUM>>1){1'b1}}};// 8'b00001111
192 // else if (fifo_rd && raddr[0]) fifo_nempty <= {fifo_nempty[ADDRESS_NUM-2:0], ~raddr[ADDRESS_BITS+1] ^ raddr[ADDRESS_BITS]};
194 
195 // fifo_dav <= fifo_full [raddr[ADDRESS_BITS:1]] ^ raddr[ADDRESS_BITS+1];
196 /// fifo_dav <= fifo_full [raddr_r[ADDRESS_BITS:1]] ^ raddr_r[ADDRESS_BITS+1];
198 
199 
200  fifo_dav2 <= fifo_dav2_w; // fifo_full2[raddr[ADDRESS_BITS:1]] ^ raddr[ADDRESS_BITS+1];
201 
202  if (mrst) flushing_mclk <= 0;
204 
207 
208  end
209 
210  ahci_dma_rd_stuff ahci_dma_rd_stuff_i (
211  .rst (mrst), // input
212  .clk (mclk), // input
213  .din_av (fifo_dav), // input
214  .din_avm_w(fifo_dav2_w), // input
215  .din_avm (fifo_dav2), // input
216  .flushing (flushing_mclk), // input
217 // .din (raddr[0]?fifo_do[63:32]: fifo_do[31:0]), // input[31:0]
218 // .dm (raddr[0]?fifo_do_vld[3:2]:fifo_do_vld[1:0]), // input[1:0]
219  .din (raddr_r[0]?fifo_do_r[63:32]: fifo_do_r[31:0]), // input[31:0]
220  .dm (raddr_r[0]?fifo_do_vld_r[3:2]:fifo_do_vld_r[1:0]), // input[1:0]
221  .din_re (fifo_rd), // output
222  .flushed (done_flush_mclk), // output reg: flush (end of last PRD is finished - data left module)
223  .dout (dout), // output[31:0] reg
224  .dout_vld (dout_vld), // output
225  .dout_re (dout_re), // input
226  .last_DW (last_DW) // output
227  );
228 
230  .EXTRA_DLY(0)
231  ) done_flush_i (
232  .rst (mrst), // input
233  .src_clk (mclk), // input
234  .dst_clk (hclk), // input
235  .in_pulse (done_flush_mclk), // input
236  .out_pulse (done_flush), // output
237  .busy() // output
238  );
239 
240  assign debug_dma_h2d = {
241  14'b0,
242  fifo_rd,
243  raddr_r[4:0],
244  fifo_do_vld_r[3:0],
245 
246  fifo_dav,
247  fifo_dav2_w,
248  fifo_dav2,
250 
252  dout_vld,
253  dout_re,
254  last_DW
255  };
256 endmodule
done_flush_i pulse_cross_clock
13061fifo_dowire[63:0]
13025ADDRESS_NUM(1<<ADDRESS_BITS
13028raddr_wwire[ADDRESS_BITS+1:0]
13029din_prevreg[63:16]
13048fifo_di_vldwire[3:0]
13060raddrwire[ADDRESS_BITS+1:0]
13026waddrreg[ADDRESS_BITS:0]
13050fifo_do_vld_rreg[3:0]
13047fifo_diwire[63:0]
ahci_dma_rd_stuff_i ahci_dma_rd_stuff
13062fifo_do_vldwire[3:0]
13058debug_waddrwire[2:0]
13041fifo_full2wire[1<<ADDRESS_BITS-1:0]
[0:ADDRESS_NUM-1] 13033fifo_ramreg[63:0]
reg [31:0] 13073dout
13059debug_raddrwire[2:0]
[WCNT_BITS-1:0] 13010wcnt
13032end_offswire[2:0]
13036fifo_nemptyreg[1<<ADDRESS_BITS-1:0]
13035fifo_fullreg[1<<ADDRESS_BITS-1:0]
13027raddr_rreg[ADDRESS_BITS+1:0]
13030qwcntrreg[WCNT_BITS-3:0]
[0:ADDRESS_NUM-1] 13034vld_ramreg[3:0]
[31:0] 13024debug_dma_h2d