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 init,
// initializes cross-clock 32->64 FIFO, disables FIFO read until confirmed back form mclk domain 56 output reg [
63:
0]
dout,
// allow only each 3-rd wr if not many 57 // input dout_av, // at least one QWORD space avaiable in AXI FIFO 59 input last_prd,
// last prd, flush partial dword if there were odd number of words transferred. valid @ start 60 // Or maybe use "last_prd"? 62 output reg [
3:
0]
dout_wstb,
// word write enable (apply to wstb, 2 wstb input bits for one dout_wstb bit) 63 output reg done,
// this PRD data sent AXI FIFO (Some partial QWORD data may be left in this module if 64 // last_prd was not set 66 // output done_flush, // finished last PRD (indicated by last_prd @ start), data left module 67 output reg fifo_nempty_mclk,
// to detect extra data from FIS, has some latency - only valid after read is stopped 70 output din_rdy,
// can accept data from HBA (multiple dwords, so reasonable latency is OK) 80 wire flush_hclk;
// TODO: Define (less than 4 left to receive)? 93 reg fifo_dav2;
// @hclk - ??? at least two are available? 95 /// wire [63:0] fifo_do = {fifo1_ram [raddr[ADDRESS_BITS:1]], fifo0_ram [raddr[ADDRESS_BITS:1]]}; 100 reg [
1:
0]
wp;
// word pointer in the output (0..3) 101 reg [
1:
0]
fp;
// pointer in the {fifo_do,fifo_do_prev} pointer (0 - fifo_do_prev[16], ..., 3 - fifo_do[0]) 102 reg [
1:
0]
wl;
// words left: 0: 1 word, ..., 3: >=4 words 103 // implementing 6 -> 23 unregistered ROM 108 reg [
3:
0]
pm;
// re_dout_wstb; 111 // reg [1:0] nwp; // Needed? 0 for all but first 112 reg [
1:
0]
nfp;
// next {fifo_do,fifo_do_prev} pointer (0 - fifo_do_prev[16], ..., 3 - fifo_do[0]) 113 reg [
2:
0]
swl;
// subtract from words_left; 115 // TODO: make separate register bits for wl == 0, wl > =4 121 // wire done_w = dout_we_r[0] && !(next_wcntr[WCNT_BITS]; 123 ((
wcntr[
1:
0] ==
0) ||
129 // wire axi_ready = dout_av && (dout_av_many || (!dout_we_r)); 134 /// assign flush_hclk = is_last_prd && !flushing && !nfp[1] && last_qword && waddr[0]; // waddr[0] - other clock domain, but OK here, 136 // it was last 1->0 before previous FIFO read. flush_hclk will only be generated for odd number of dwords 139 assign dout_we =
dout_we_r[
0];
// dout_we_r[0] - write to dout, use dout_av && (!(|dout_we_r) || dout_av_many) to enable dout_we_r[0]<= 158 // reg [ADDRESS_BITS : 0] raddr; // 1 extra bit 162 /// else if (fifo_rd && raddr[0]) fifo_nempty <= {fifo_nempty[ADDRESS_NUM-2:0],raddr[ADDRESS_BITS] ^ raddr[ADDRESS_BITS-1]}; 166 /// fifo_dav <= !init && en_fifo_rd && (fifo_full [raddr[ADDRESS_BITS:1]] ^ raddr[ADDRESS_BITS]); 168 /// fifo_dav2 <= !init && en_fifo_rd && (fifo_full2[raddr[ADDRESS_BITS:1]]); //?^ raddr[ADDRESS_BITS]); // FIXME 175 // flushing will only be set for the last dword in last PRD if total number of dwords is ODD. 176 // Odd number of words should be handled outside of this module (before) 191 else if (
dout_we_w)
wp <=
0;
// all but possibly wirst QWORD are aligned to th low word 193 if (
init)
fp <=
3;
// only reset for the first PRD, points to the beginning of the fifo_do (fifo_do_prev - empty) 196 // words left: 0: 1 word, ..., 3: >=4 words 216 default:
dout[
31:
16] <=
16'bx;
// should never get here 226 default:
dout[
47:
32] <=
16'bx;
// should never get here 237 default:
dout[
63:
48] <=
16'bx;
// should never get here 245 output reg [63:0] dout, // allow only each 3-rd wr if not many 246 input dout_av, // at least one QWORD space avaiable in AXI FIFO 247 input dout_av_many, // several QWORD space avaiable in AXI FIFO 248 input last_prd, // last prd, flush partial dword if there were odd number of words transferred. valid @ start 249 // Or maybe use "last_prd"? 251 output reg [3:0] dout_wstb, // word write enable (apply to wstb, 2 wstb input bits for one dout_wstb bit) 252 output reg done, // this PRD data sent AXI FIFO (Some partial QWORD data may be left in this module if 256 always @* case ({wp, fp, wl}) 257 6'h00: begin mx0 <= 0; mx1 <= 1; mx2 <= 2; mx3 <= 3; pm <= 4'b0001; fifo_rd <= 0; nfp <= 1; swl <= 1; end 274 /// else if (fifo_wr) fifo_full <= {fifo_full[ADDRESS_NUM-2:0], waddr[ADDRESS_BITS+1]}; 282 /// fifo_nempty_mclk <= (fifo_full [raddr[ADDRESS_BITS:1]] ^ raddr[ADDRESS_BITS]); // only valid after read is stopped 288 // hclk -> mclk cross-clock synchronization 311 // mclk -> hclk cross-clock synchronization 326 .rst (mrst), // input 327 .src_clk (mclk), // input 328 .dst_clk (hclk), // input 329 .in_pulse (flush_mclk), // input 330 .out_pulse (flush_conf), // output 335 wl: 0: left 1 word, 1: left 2 words, 2: left 3 words, 3: left >=4 words 336 wp (pointer in the output qword, only first in PRD can be non-zero) 0: word 0 of output QW, ... 337 mx0 0: use fifo_do_prev[16], 1: fifo_do_prev[32], 2:fifo_do_prev[48], 3:fifo_do[0]; 338 mx1 0: use fifo_do_prev[16], 1: fifo_do_prev[32], 2:fifo_do_prev[48], 3:fifo_do[0], 4:fifo_do[16]; 339 mx2 0: use fifo_do_prev[16], 1: fifo_do_prev[32], 2:fifo_do_prev[48], 3:fifo_do[0], 4:fifo_do[16], 5:fifo_do[32]; 340 mx3 0: use fifo_do_prev[16], 1: fifo_do_prev[32], 2:fifo_do_prev[48], 3:fifo_do[0], 4:fifo_do[16], 5:fifo_do[32], 6:fifo_do[48]; 341 fp/nfp: 0 - pointer to fifo_do_prev[16], 1 : fifo_do_prev[32], 2: fifo_do_prev[48], 3: fifo_do[0]
[0:ADDRESS_NUM-1] 13120fifo0_ramreg[31:0]
13132fifo_nemptyreg[1<<ADDRESS_BITS-1:0]
13157wcntrreg[WCNT_BITS-1:0]
reg 13115fifo_nempty_mclk
[WCNT_BITS-1:0] 13104wcnt
init_confirm_i pulse_cross_clock
[0:ADDRESS_NUM-1] 13121fifo1_ramreg[31:0]
13131fifo_fullreg[1<<ADDRESS_BITS-1:0]
13128raddrreg[ADDRESS_BITS:0]
13158next_wcntrwire[WCNT_BITS-1:0]
13134fifo_full2wire[1<<ADDRESS_BITS-1:0]
13119ADDRESS_NUM(1<<ADDRESS_BITS
13130fifo_do_prevreg[63:16]
13129waddrreg[ADDRESS_BITS+1:0]