Loading utils/ahci_dma_rd_fifo.v +93 −5 Original line number Original line Diff line number Diff line Loading @@ -23,23 +23,111 @@ `timescale 1ns/1ps `timescale 1ns/1ps module ahci_dma_rd_fifo#( module ahci_dma_rd_fifo#( parameter WCNT_BITS = 21 parameter WCNT_BITS = 21, parameter ADDRESS_BITS = 3 )( )( input mrst, input mrst, input hrst, input hrst, input mclk, input mclk, input hclk, input hclk, input [WCNT_BITS-1:0] wcnt, // hclk domain input [WCNT_BITS-1:0] wcnt, // decrementing word counter, 0- based (0 need 1, 1 - need 2, ...) valid @ start input [1:0] woffs, // 2 LSBs of the initial word address - valid @ start input start, // start transfer input [63:0] din, input [63:0] din, input din_av, input din_av, input din_av_many, input din_av_many, input flush, // last prd, flush partial dword if there were odd number of words transferred // Or maybe use "last_prd"? output din_re, output din_re, output done, // mclk domain output [31:0] dout, output [31:0] dout, output dout_av, output dout_vld, output dout_av_many, input dout_re input dout_re ); ); localparam ADDRESS_NUM = (1<<ADDRESS_BITS); // 8 for ADDRESS_BITS==3 reg [ADDRESS_BITS : 0] waddr; // 1 extra bit 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 extra_in; reg busy; 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<<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; wire fifo_rd; reg hrst_mclk; wire [(1<<ADDRESS_BITS)-1:0] fifo_full2 = {fifo_full[0],fifo_full[ADDRESS_NUM-1:1]}; // 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 [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 always @ (posedge hclk) begin if (hrst) busy <= 0; else if (start) busy <= 1; else if (done) busy <= 0; 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; if (hrst) fifo_full <= 0; else if (fifo_wr) fifo_full <= {fifo_full[ADDRESS_NUM-2:0],waddr[ADDRESS_BITS]}; if (hrst) waddr <= 0; else if (fifo_wr) waddr <= waddr+1; fifo_half_hclk <= fifo_nempty [waddr[ADDRESS_BITS-1:0]] ^ waddr[ADDRESS_BITS]; if (din_re) din_prev[63:16] <= din[63:16]; 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; end always @ (posedge hclk) begin hrst_mclk <= hrst; 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]}; fifo_dav <= fifo_full [raddr[ADDRESS_BITS:1]] ^ raddr[ADDRESS_BITS+1]; fifo_dav2 <= fifo_full2[raddr[ADDRESS_BITS:1]]; end 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 .dout (dout), // output[31:0] reg .dout_vld (dout_vld), // output .dout_re (dout_re) // input ); endmodule endmodule Loading utils/ahci_dma_rd_stuff.v +9 −8 Original line number Original line Diff line number Diff line Loading @@ -37,12 +37,15 @@ module ahci_dma_rd_stuff( reg hr_full; reg hr_full; reg dout_vld_r; reg dout_vld_r; reg flushing; reg flushing; wire din_av_safe = din_av && (din_avm || !din_re); reg din_av_safe_r; wire [1:0] dav_in = {2{din_av_safe}} & dm; wire [1:0] dav_in = {2{din_av_safe_r}} & dm; wire two_words_avail = &dav_in || (|dav_in && hr_full); wire two_words_avail = &dav_in || (|dav_in && hr_full); assign din_re = (din_av_safe && !(|dm)) || ((!dout_vld_r || dout_re) && (two_words_avail)) ; // flush assign din_re = (din_av_safe_r && !(|dm)) || ((!dout_vld_r || dout_re) && (two_words_avail)) ; // flush assign dout_vld = dout_vld_r; assign dout_vld = dout_vld_r; always @ (posedge clk) begin always @ (posedge clk) begin if (rst) din_av_safe_r <= 0; else din_av_safe_r <= din_av && (din_avm || !din_re); if ((!dout_vld_r || dout_re) && (two_words_avail || flushing)) begin if ((!dout_vld_r || dout_re) && (two_words_avail || flushing)) begin if (hr_full) dout[15: 0] <= hr; if (hr_full) dout[15: 0] <= hr; else dout[15: 0] <= din[15: 0]; else dout[15: 0] <= din[15: 0]; Loading @@ -52,7 +55,8 @@ module ahci_dma_rd_stuff( end end // todo add reset/flush // todo add reset/flush if (!dout_vld_r || dout_re) if (rst) hr_full <= 0; else if (!dout_vld_r || dout_re) // 2 but not 3 sources available // 2 but not 3 sources available if (flushing || ((two_words_avail) && ! (&dav_in && hr_full))) hr_full <= 0; if (flushing || ((two_words_avail) && ! (&dav_in && hr_full))) hr_full <= 0; else if (dav_in[0] ^ dav_in[1]) hr_full <= 1; else if (dav_in[0] ^ dav_in[1]) hr_full <= 1; Loading @@ -68,10 +72,7 @@ module ahci_dma_rd_stuff( else if (flush) flushing <= 1; else if (flush) flushing <= 1; else if ((!dout_vld_r || dout_re) && !(&dav_in && hr_full)) flushing <= 0; else if ((!dout_vld_r || dout_re) && !(&dav_in && hr_full)) flushing <= 0; end end endmodule endmodule Loading
utils/ahci_dma_rd_fifo.v +93 −5 Original line number Original line Diff line number Diff line Loading @@ -23,23 +23,111 @@ `timescale 1ns/1ps `timescale 1ns/1ps module ahci_dma_rd_fifo#( module ahci_dma_rd_fifo#( parameter WCNT_BITS = 21 parameter WCNT_BITS = 21, parameter ADDRESS_BITS = 3 )( )( input mrst, input mrst, input hrst, input hrst, input mclk, input mclk, input hclk, input hclk, input [WCNT_BITS-1:0] wcnt, // hclk domain input [WCNT_BITS-1:0] wcnt, // decrementing word counter, 0- based (0 need 1, 1 - need 2, ...) valid @ start input [1:0] woffs, // 2 LSBs of the initial word address - valid @ start input start, // start transfer input [63:0] din, input [63:0] din, input din_av, input din_av, input din_av_many, input din_av_many, input flush, // last prd, flush partial dword if there were odd number of words transferred // Or maybe use "last_prd"? output din_re, output din_re, output done, // mclk domain output [31:0] dout, output [31:0] dout, output dout_av, output dout_vld, output dout_av_many, input dout_re input dout_re ); ); localparam ADDRESS_NUM = (1<<ADDRESS_BITS); // 8 for ADDRESS_BITS==3 reg [ADDRESS_BITS : 0] waddr; // 1 extra bit 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 extra_in; reg busy; 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<<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; wire fifo_rd; reg hrst_mclk; wire [(1<<ADDRESS_BITS)-1:0] fifo_full2 = {fifo_full[0],fifo_full[ADDRESS_NUM-1:1]}; // 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 [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 always @ (posedge hclk) begin if (hrst) busy <= 0; else if (start) busy <= 1; else if (done) busy <= 0; 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; if (hrst) fifo_full <= 0; else if (fifo_wr) fifo_full <= {fifo_full[ADDRESS_NUM-2:0],waddr[ADDRESS_BITS]}; if (hrst) waddr <= 0; else if (fifo_wr) waddr <= waddr+1; fifo_half_hclk <= fifo_nempty [waddr[ADDRESS_BITS-1:0]] ^ waddr[ADDRESS_BITS]; if (din_re) din_prev[63:16] <= din[63:16]; 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; end always @ (posedge hclk) begin hrst_mclk <= hrst; 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]}; fifo_dav <= fifo_full [raddr[ADDRESS_BITS:1]] ^ raddr[ADDRESS_BITS+1]; fifo_dav2 <= fifo_full2[raddr[ADDRESS_BITS:1]]; end 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 .dout (dout), // output[31:0] reg .dout_vld (dout_vld), // output .dout_re (dout_re) // input ); endmodule endmodule Loading
utils/ahci_dma_rd_stuff.v +9 −8 Original line number Original line Diff line number Diff line Loading @@ -37,12 +37,15 @@ module ahci_dma_rd_stuff( reg hr_full; reg hr_full; reg dout_vld_r; reg dout_vld_r; reg flushing; reg flushing; wire din_av_safe = din_av && (din_avm || !din_re); reg din_av_safe_r; wire [1:0] dav_in = {2{din_av_safe}} & dm; wire [1:0] dav_in = {2{din_av_safe_r}} & dm; wire two_words_avail = &dav_in || (|dav_in && hr_full); wire two_words_avail = &dav_in || (|dav_in && hr_full); assign din_re = (din_av_safe && !(|dm)) || ((!dout_vld_r || dout_re) && (two_words_avail)) ; // flush assign din_re = (din_av_safe_r && !(|dm)) || ((!dout_vld_r || dout_re) && (two_words_avail)) ; // flush assign dout_vld = dout_vld_r; assign dout_vld = dout_vld_r; always @ (posedge clk) begin always @ (posedge clk) begin if (rst) din_av_safe_r <= 0; else din_av_safe_r <= din_av && (din_avm || !din_re); if ((!dout_vld_r || dout_re) && (two_words_avail || flushing)) begin if ((!dout_vld_r || dout_re) && (two_words_avail || flushing)) begin if (hr_full) dout[15: 0] <= hr; if (hr_full) dout[15: 0] <= hr; else dout[15: 0] <= din[15: 0]; else dout[15: 0] <= din[15: 0]; Loading @@ -52,7 +55,8 @@ module ahci_dma_rd_stuff( end end // todo add reset/flush // todo add reset/flush if (!dout_vld_r || dout_re) if (rst) hr_full <= 0; else if (!dout_vld_r || dout_re) // 2 but not 3 sources available // 2 but not 3 sources available if (flushing || ((two_words_avail) && ! (&dav_in && hr_full))) hr_full <= 0; if (flushing || ((two_words_avail) && ! (&dav_in && hr_full))) hr_full <= 0; else if (dav_in[0] ^ dav_in[1]) hr_full <= 1; else if (dav_in[0] ^ dav_in[1]) hr_full <= 1; Loading @@ -68,10 +72,7 @@ module ahci_dma_rd_stuff( else if (flush) flushing <= 1; else if (flush) flushing <= 1; else if ((!dout_vld_r || dout_re) && !(&dav_in && hr_full)) flushing <= 0; else if ((!dout_vld_r || dout_re) && !(&dav_in && hr_full)) flushing <= 0; end end endmodule endmodule