Commit e2fb6292 authored by Andrey Filippov's avatar Andrey Filippov
Browse files

Finished initial coding for PRD Host->Device modules

parent f1543888
Loading
Loading
Loading
Loading
+71 −28
Original line number Diff line number Diff line
@@ -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,
@@ -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;
@@ -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;
@@ -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]};
        
@@ -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
+6 −1
Original line number Diff line number Diff line
@@ -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)
@@ -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);
@@ -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