Loading utils/ahci_dma_rd_fifo.v +71 −28 Original line number Diff line number Diff line Loading @@ -37,10 +37,12 @@ module ahci_dma_rd_fifo#( input [63:0] din, input din_av, input din_av_many, input flush, // last prd, flush partial dword if there were odd number of words transferred input last_prd, // last prd, flush partial dword if there were odd number of words transferred. valid @ start // Or maybe use "last_prd"? output din_re, output done, output reg done, // this PRD data sent to cross-clock FIFO (may result in only half-dword sent out), // OK to fetch another PRD (if it was not the last) output done_flush, // finished last PRD (indicated by last_prd @ start), data left module // mclk domain output [31:0] dout, output dout_vld, Loading @@ -51,14 +53,15 @@ module ahci_dma_rd_fifo#( reg [ADDRESS_BITS+1:0] raddr; // 1 extra bit reg [63:16] din_prev; // only 48 bits are needed reg [WCNT_BITS-3:0] qwcntr; reg some_offs; // reg some_offs; reg extra_in; reg busy; reg din_last_w = din_re && (qwcntr==0); // reg din_last_w = din_re && (qwcntr==0); wire [2:0] end_offs = wcnt[1:0] + woffs; reg [63:0] fifo_ram [0: ADDRESS_NUM - 1]; reg [3:0] vld_ram [0: ADDRESS_NUM - 1]; reg [1:0] flush_ram [0: ADDRESS_NUM - 1]; reg [(1<<ADDRESS_BITS)-1:0] fifo_full; // set in write clock domain reg [(1<<ADDRESS_BITS)-1:0] fifo_nempty;// set in read clock domain wire fifo_wr; Loading @@ -68,23 +71,43 @@ module ahci_dma_rd_fifo#( // wire [(1<<ADDRESS_BITS)-1:0] fifo_nempty_half = {fifo_nempty[(ADDRESS_NUM>>1)-1:0],fifo_full[ADDRESS_NUM-1: ADDRESS_NUM>>1]}; reg fifo_dav; // @mclk reg fifo_dav2; // @mclk reg fifo_half_hclk; reg fifo_half_hclk; // Half Fifo is empty, OK to write reg [1:0] woffs_r; 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]}): (woffs_r[0] ? {din[15:0],din_prev[63:16]} : din[63:0]); wire [3:0] fifo_di_vld; // Assign wire [3:0] fifo_di_vld; wire [1:0] fifo_di_flush; // Assign wire [63:0] fifo_do = fifo_ram [raddr[ADDRESS_BITS:1]]; wire [3:0] fifo_do_vld = vld_ram [raddr[ADDRESS_BITS:1]]; wire [1:0] fifo_do_flush = flush_ram[raddr[ADDRESS_BITS:1]]; reg din_av_safe_r; reg en_fifo_wr; reg [3:0] last_mask; reg flush_r; wire done_flush_mclk; assign din_re = busy && fifo_half_hclk && din_av_safe_r; assign fifo_wr = en_fifo_wr && fifo_half_hclk && (din_av_safe_r || !busy); assign fifo_di_vld = (busy && (!extra_in || (qwcntr != 0)))? 4'hf : last_mask ; assign fifo_di_flush = ((busy && (!extra_in || (qwcntr != 0))) || !flush_r)? 2'h0 : {|last_mask[3:2], ~(|last_mask[3:2])} ; always @ (posedge hclk) begin if (hrst) busy <= 0; else if (start) busy <= 1; else if (done) busy <= 0; else if (din_re && (qwcntr == 0)) busy <= 0; done <= busy && din_re && (qwcntr == 0); if (hrst) en_fifo_wr <= 0; else if (start) en_fifo_wr <= (wcnt[1:0] == 0); else if (din_re || fifo_wr) en_fifo_wr <= busy && ((qwcntr != 0) || extra_in); if (start) qwcntr <= wcnt[WCNT_BITS-1:2]; else if (din_re) qwcntr <= qwcntr - 1; if (start) some_offs <= wcnt[1:0] != 0; if (start) extra_in <= end_offs[2]; if (start) woffs_r <= woffs; Loading @@ -101,11 +124,23 @@ module ahci_dma_rd_fifo#( if (fifo_wr) fifo_ram[waddr[ADDRESS_BITS-1:0]] <= fifo_di; if (fifo_wr) vld_ram [waddr[ADDRESS_BITS-1:0]] <= fifo_di_vld; if (fifo_wr) flush_ram[waddr[ADDRESS_BITS-1:0]] <= fifo_di_flush; if (hrst) din_av_safe_r <= 0; else din_av_safe_r <= din_av && (din_av_many || !din_re); if (start) last_mask <= {&wcnt, wcnt[1], |wcnt, 1'b1}; if (start) flush_r <= last_prd; end always @ (posedge hclk) begin hrst_mclk <= hrst; if (hrst_mclk) raddr <= 0; else if (fifo_rd) raddr <= raddr + 1; if (hrst_mclk) fifo_nempty <= {{(ADDRESS_NUM>>1){1'b0}},{(ADDRESS_NUM>>1){1'b1}}};// 8'b00001111 else if (fifo_rd && raddr[0]) fifo_nempty <= {fifo_nempty[ADDRESS_NUM-2:0],raddr[ADDRESS_BITS+1] ^ raddr[ADDRESS_BITS]}; Loading @@ -116,19 +151,27 @@ module ahci_dma_rd_fifo#( ahci_dma_rd_stuff ahci_dma_rd_stuff_i ( .rst (mrst), // input .clk (mclk), // input .din_av (), // input .din_avm (), // input .flush (), // input .din (), // input[31:0] .dm (), // input[1:0] .din_re (), // output .din_av (fifo_dav), // input .din_avm (fifo_dav2), // input .flush (raddr[0]?fifo_do_flush[1]:fifo_do_flush[0]), // input .din (raddr[0]?fifo_do[63:32]: fifo_do[31:0]), // input[31:0] .dm (raddr[0]?fifo_do_vld[3:2]:fifo_do_vld[1:0]), // input[1:0] .din_re (fifo_rd), // output .flushed (done_flush_mclk), // output reg: flush (end of last PRD is finished - data left module) .dout (dout), // output[31:0] reg .dout_vld (dout_vld), // output .dout_re (dout_re) // input ); pulse_cross_clock #( .EXTRA_DLY(0) ) done_flush_i ( .rst (mrst), // input .src_clk (mclk), // input .dst_clk (hclk), // input .in_pulse (done_flush_mclk), // input .out_pulse (done_flush), // output .busy() // output ); endmodule utils/ahci_dma_rd_stuff.v +6 −1 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ module ahci_dma_rd_stuff( input [31:0] din, // 32-bit input dfata input [1:0] dm, // data mask showing which (if any) words in input dword are valid output din_re, // read input data output reg flushed, // flush (end of last PRD is finished - data left module) output reg [31:0] dout, // output 32-bit data output dout_vld, // output data valid input dout_re // consumer reads output data (should be anded with dout_vld) Loading @@ -37,6 +38,7 @@ module ahci_dma_rd_stuff( reg hr_full; reg dout_vld_r; reg flushing; reg flushing_d; reg din_av_safe_r; wire [1:0] dav_in = {2{din_av_safe_r}} & dm; wire two_words_avail = &dav_in || (|dav_in && hr_full); Loading Loading @@ -72,6 +74,9 @@ module ahci_dma_rd_stuff( else if (flush) flushing <= 1; else if ((!dout_vld_r || dout_re) && !(&dav_in && hr_full)) flushing <= 0; flushing_d <= flushing; flushed <= flushing_d && !flushing; // 1 cycle delay end endmodule Loading Loading
utils/ahci_dma_rd_fifo.v +71 −28 Original line number Diff line number Diff line Loading @@ -37,10 +37,12 @@ module ahci_dma_rd_fifo#( input [63:0] din, input din_av, input din_av_many, input flush, // last prd, flush partial dword if there were odd number of words transferred input last_prd, // last prd, flush partial dword if there were odd number of words transferred. valid @ start // Or maybe use "last_prd"? output din_re, output done, output reg done, // this PRD data sent to cross-clock FIFO (may result in only half-dword sent out), // OK to fetch another PRD (if it was not the last) output done_flush, // finished last PRD (indicated by last_prd @ start), data left module // mclk domain output [31:0] dout, output dout_vld, Loading @@ -51,14 +53,15 @@ module ahci_dma_rd_fifo#( reg [ADDRESS_BITS+1:0] raddr; // 1 extra bit reg [63:16] din_prev; // only 48 bits are needed reg [WCNT_BITS-3:0] qwcntr; reg some_offs; // reg some_offs; reg extra_in; reg busy; reg din_last_w = din_re && (qwcntr==0); // reg din_last_w = din_re && (qwcntr==0); wire [2:0] end_offs = wcnt[1:0] + woffs; reg [63:0] fifo_ram [0: ADDRESS_NUM - 1]; reg [3:0] vld_ram [0: ADDRESS_NUM - 1]; reg [1:0] flush_ram [0: ADDRESS_NUM - 1]; reg [(1<<ADDRESS_BITS)-1:0] fifo_full; // set in write clock domain reg [(1<<ADDRESS_BITS)-1:0] fifo_nempty;// set in read clock domain wire fifo_wr; Loading @@ -68,23 +71,43 @@ module ahci_dma_rd_fifo#( // wire [(1<<ADDRESS_BITS)-1:0] fifo_nempty_half = {fifo_nempty[(ADDRESS_NUM>>1)-1:0],fifo_full[ADDRESS_NUM-1: ADDRESS_NUM>>1]}; reg fifo_dav; // @mclk reg fifo_dav2; // @mclk reg fifo_half_hclk; reg fifo_half_hclk; // Half Fifo is empty, OK to write reg [1:0] woffs_r; 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]}): (woffs_r[0] ? {din[15:0],din_prev[63:16]} : din[63:0]); wire [3:0] fifo_di_vld; // Assign wire [3:0] fifo_di_vld; wire [1:0] fifo_di_flush; // Assign wire [63:0] fifo_do = fifo_ram [raddr[ADDRESS_BITS:1]]; wire [3:0] fifo_do_vld = vld_ram [raddr[ADDRESS_BITS:1]]; wire [1:0] fifo_do_flush = flush_ram[raddr[ADDRESS_BITS:1]]; reg din_av_safe_r; reg en_fifo_wr; reg [3:0] last_mask; reg flush_r; wire done_flush_mclk; assign din_re = busy && fifo_half_hclk && din_av_safe_r; assign fifo_wr = en_fifo_wr && fifo_half_hclk && (din_av_safe_r || !busy); assign fifo_di_vld = (busy && (!extra_in || (qwcntr != 0)))? 4'hf : last_mask ; assign fifo_di_flush = ((busy && (!extra_in || (qwcntr != 0))) || !flush_r)? 2'h0 : {|last_mask[3:2], ~(|last_mask[3:2])} ; always @ (posedge hclk) begin if (hrst) busy <= 0; else if (start) busy <= 1; else if (done) busy <= 0; else if (din_re && (qwcntr == 0)) busy <= 0; done <= busy && din_re && (qwcntr == 0); if (hrst) en_fifo_wr <= 0; else if (start) en_fifo_wr <= (wcnt[1:0] == 0); else if (din_re || fifo_wr) en_fifo_wr <= busy && ((qwcntr != 0) || extra_in); if (start) qwcntr <= wcnt[WCNT_BITS-1:2]; else if (din_re) qwcntr <= qwcntr - 1; if (start) some_offs <= wcnt[1:0] != 0; if (start) extra_in <= end_offs[2]; if (start) woffs_r <= woffs; Loading @@ -101,11 +124,23 @@ module ahci_dma_rd_fifo#( if (fifo_wr) fifo_ram[waddr[ADDRESS_BITS-1:0]] <= fifo_di; if (fifo_wr) vld_ram [waddr[ADDRESS_BITS-1:0]] <= fifo_di_vld; if (fifo_wr) flush_ram[waddr[ADDRESS_BITS-1:0]] <= fifo_di_flush; if (hrst) din_av_safe_r <= 0; else din_av_safe_r <= din_av && (din_av_many || !din_re); if (start) last_mask <= {&wcnt, wcnt[1], |wcnt, 1'b1}; if (start) flush_r <= last_prd; end always @ (posedge hclk) begin hrst_mclk <= hrst; if (hrst_mclk) raddr <= 0; else if (fifo_rd) raddr <= raddr + 1; if (hrst_mclk) fifo_nempty <= {{(ADDRESS_NUM>>1){1'b0}},{(ADDRESS_NUM>>1){1'b1}}};// 8'b00001111 else if (fifo_rd && raddr[0]) fifo_nempty <= {fifo_nempty[ADDRESS_NUM-2:0],raddr[ADDRESS_BITS+1] ^ raddr[ADDRESS_BITS]}; Loading @@ -116,19 +151,27 @@ module ahci_dma_rd_fifo#( ahci_dma_rd_stuff ahci_dma_rd_stuff_i ( .rst (mrst), // input .clk (mclk), // input .din_av (), // input .din_avm (), // input .flush (), // input .din (), // input[31:0] .dm (), // input[1:0] .din_re (), // output .din_av (fifo_dav), // input .din_avm (fifo_dav2), // input .flush (raddr[0]?fifo_do_flush[1]:fifo_do_flush[0]), // input .din (raddr[0]?fifo_do[63:32]: fifo_do[31:0]), // input[31:0] .dm (raddr[0]?fifo_do_vld[3:2]:fifo_do_vld[1:0]), // input[1:0] .din_re (fifo_rd), // output .flushed (done_flush_mclk), // output reg: flush (end of last PRD is finished - data left module) .dout (dout), // output[31:0] reg .dout_vld (dout_vld), // output .dout_re (dout_re) // input ); pulse_cross_clock #( .EXTRA_DLY(0) ) done_flush_i ( .rst (mrst), // input .src_clk (mclk), // input .dst_clk (hclk), // input .in_pulse (done_flush_mclk), // input .out_pulse (done_flush), // output .busy() // output ); endmodule
utils/ahci_dma_rd_stuff.v +6 −1 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ module ahci_dma_rd_stuff( input [31:0] din, // 32-bit input dfata input [1:0] dm, // data mask showing which (if any) words in input dword are valid output din_re, // read input data output reg flushed, // flush (end of last PRD is finished - data left module) output reg [31:0] dout, // output 32-bit data output dout_vld, // output data valid input dout_re // consumer reads output data (should be anded with dout_vld) Loading @@ -37,6 +38,7 @@ module ahci_dma_rd_stuff( reg hr_full; reg dout_vld_r; reg flushing; reg flushing_d; reg din_av_safe_r; wire [1:0] dav_in = {2{din_av_safe_r}} & dm; wire two_words_avail = &dav_in || (|dav_in && hr_full); Loading Loading @@ -72,6 +74,9 @@ module ahci_dma_rd_stuff( else if (flush) flushing <= 1; else if ((!dout_vld_r || dout_re) && !(&dav_in && hr_full)) flushing <= 0; flushing_d <= flushing; flushed <= flushing_d && !flushing; // 1 cycle delay end endmodule Loading