Loading ahci/ahci_ctrl_stat.v +1 −1 Original line number Original line Diff line number Diff line Loading @@ -124,7 +124,7 @@ module ahci_ctrl_stat #( input ssts_det_ndnp, // no device detected, phy communication not established input ssts_det_ndnp, // no device detected, phy communication not established input ssts_det_dnp, // device detected, but phy communication not established input ssts_det_dnp, // device detected, but phy communication not established input ssts_det_dp, // device detected, phy communication established input ssts_det_dp, // device detected, phy communication established input ssts_det_offline, // device offline input ssts_det_offline, // device offline or BIST output [3:0] ssts_det, // current value of PxSSTS.DET output [3:0] ssts_det, // current value of PxSSTS.DET // SCR2:SControl (written by software only) // SCR2:SControl (written by software only) Loading ahci/ahci_dma.v +33 −7 Original line number Original line Diff line number Diff line Loading @@ -65,11 +65,11 @@ module ahci_dma ( // After the first 0x80 bytes of the Command Table are read out, this module will read/process PRDs, // After the first 0x80 bytes of the Command Table are read out, this module will read/process PRDs, // not forwarding them to the output // not forwarding them to the output output prd_done, // prd done (regardless of the interrupt) - data transfer of one PRD is finished (any direction) output prd_done, // @mclk prd done (regardless of the interrupt) - data transfer of one PRD is finished (any direction) input prd_irq_clear, // reset pending prd_irq output prd_irq, // prd interrupt, if enabled output reg prd_irq_pend, // prd interrupt pending. This is just a condition for irq - actual will be generated after FIS OK output reg cmd_busy, // all commands output reg cmd_busy, // all commands output cmd_done, output cmd_done, // @ mclk // Data System memory -> HBA interface @ mclk // Data System memory -> HBA interface @ mclk output [31:0] sys_out, // 32-bit data from the system memory to HBA (dma data) output [31:0] sys_out, // 32-bit data from the system memory to HBA (dma data) Loading @@ -81,6 +81,8 @@ module ahci_dma ( output sys_nfull, // internal FIFO has room for more data (will decide - how big reserved space to keep) output sys_nfull, // internal FIFO has room for more data (will decide - how big reserved space to keep) input sys_we, input sys_we, output extra_din, // all DRDs are transferred to memory, but FIFO has some data. Valid when transfer is stopped // axi_hp signals write channel // axi_hp signals write channel // write address // write address output [31:0] afi_awaddr, output [31:0] afi_awaddr, Loading Loading @@ -228,8 +230,10 @@ module ahci_dma ( reg [3:0] dev_rd_id; reg [3:0] dev_rd_id; reg [5:0] afi_id; // common for 3 channels reg [5:0] afi_id; // common for 3 channels assign prd_done = done_dev_wr || done_dev_rd; wire fifo_nempty_mclk; assign prd_irq = data_irq && prd_done; reg en_extra_din_r; // assign prd_done = done_dev_wr || done_dev_rd; assign cmd_done_hclk = ((ct_busy_r==2'b10) && (prdtl_mclk == 0)) || done_flush || done_dev_rd; assign cmd_done_hclk = ((ct_busy_r==2'b10) && (prdtl_mclk == 0)) || done_flush || done_dev_rd; assign ct_done = (ct_busy_r == 2'b10); assign ct_done = (ct_busy_r == 2'b10); assign first_prd_fetch = ct_over_prd_enabled == 2'b01; assign first_prd_fetch = ct_over_prd_enabled == 2'b01; Loading Loading @@ -269,7 +273,7 @@ module ahci_dma ( assign afi_arburst = 2'h1; assign afi_arburst = 2'h1; assign afi_arqos = 4'h0; assign afi_arqos = 4'h0; assign afi_rdissuecap1en = 1'b0; assign afi_rdissuecap1en = 1'b0; assign extra_din = en_extra_din_r && fifo_nempty_mclk; always @ (posedge mclk) begin always @ (posedge mclk) begin if (ct_re) ct_data <= ct_data_ram[ct_addr]; if (ct_re) ct_data <= ct_data_ram[ct_addr]; if (ctba_ld) ctba_r <= ctba[31:7]; if (ctba_ld) ctba_r <= ctba[31:7]; Loading @@ -292,6 +296,13 @@ module ahci_dma ( prd_start_r <= prd_start; prd_start_r <= prd_start; if (mrst || prd_irq_clear ||cmd_start || cmd_abort) prd_irq_pend <= 0; else if (data_irq && prd_done) prd_irq_pend <= 1; if (mrst || cmd_start || cmd_abort) en_extra_din_r <= 0; else if (cmd_done) en_extra_din_r <= 1; end end Loading Loading @@ -472,6 +483,7 @@ module ahci_dma ( .dout_wstb (afi_wstb4), // output[3:0] reg .dout_wstb (afi_wstb4), // output[3:0] reg .done (done_dev_rd), // output reg .done (done_dev_rd), // output reg .busy (), // output .busy (), // output .fifo_nempty_mclk (fifo_nempty_mclk), // output reg .din (sys_in), // input[31:0] .din (sys_in), // input[31:0] .din_rdy (sys_nfull), // output .din_rdy (sys_nfull), // output .din_avail (sys_we) // input .din_avail (sys_we) // input Loading Loading @@ -535,5 +547,19 @@ module ahci_dma ( .busy() // output .busy() // output ); ); pulse_cross_clock #( .EXTRA_DLY(0) ) prd_done_mclk_i ( .rst (hrst), // input .src_clk (hclk), // input .dst_clk (mclk), // input .in_pulse (done_dev_wr || done_dev_rd), // input .out_pulse (prd_done), // output .busy() // output ); endmodule endmodule ahci/ahci_dma_wr_fifo.v +3 −1 Original line number Original line Diff line number Diff line Loading @@ -59,7 +59,7 @@ module ahci_dma_wr_fifo#( // last_prd was not set // last_prd was not set output busy, output busy, // output done_flush, // finished last PRD (indicated by last_prd @ start), data left module // output done_flush, // finished last PRD (indicated by last_prd @ start), data left module output reg fifo_nempty_mclk, // to detect extra data from FIS, has some latency - only valid after read is stopped // mclk domain // mclk domain input [31:0] din, input [31:0] din, output din_rdy, // can accept data from HBA (multiple dwords, so reasonable latency is OK) output din_rdy, // can accept data from HBA (multiple dwords, so reasonable latency is OK) Loading Loading @@ -268,6 +268,8 @@ module ahci_dma_wr_fifo#( if (fifo_wr && !waddr[0]) fifo0_ram[waddr[ADDRESS_BITS:1]] <= din; if (fifo_wr && !waddr[0]) fifo0_ram[waddr[ADDRESS_BITS:1]] <= din; if (fifo_wr && waddr[0]) fifo1_ram[waddr[ADDRESS_BITS:1]] <= din; if (fifo_wr && waddr[0]) fifo1_ram[waddr[ADDRESS_BITS:1]] <= din; fifo_nempty_mclk <= (fifo_full [raddr[ADDRESS_BITS:1]] ^ raddr[ADDRESS_BITS]); // only valid after read is stopped end end Loading ahci/ahci_fis_receive.v +52 −18 Original line number Original line Diff line number Diff line Loading @@ -36,6 +36,9 @@ module ahci_fis_receive#( input mclk, // for command/status input mclk, // for command/status // Control Interface // Control Interface output reg fis_first_vld, // fis_first contains valid FIS header, reset by get_* output reg fis_first_vld, // fis_first contains valid FIS header, reset by get_* // Debug features output fis_first_invalid, // Some data available from FIFO, but not FIS head input fis_first_flush, // Skip FIFO data until empty or FIS head // Receiving FIS // Receiving FIS input get_dsfis, input get_dsfis, input get_psfis, input get_psfis, Loading @@ -49,6 +52,8 @@ module ahci_fis_receive#( output reg fis_ok, // FIS done, checksum OK reset by starting a new get FIS output reg fis_ok, // FIS done, checksum OK reset by starting a new get FIS output reg fis_err, // FIS done, checksum ERROR reset by starting a new get FIS output reg fis_err, // FIS done, checksum ERROR reset by starting a new get FIS output fis_ferr, // FIS done, fatal error - FIS too long output fis_ferr, // FIS done, fatal error - FIS too long input dma_prds_done, // dma is done - check if FIS is done (some data may get stuck in dma FIFO - reported separately) output fis_extra, // all wanted data got, FIS may have extra data (non-fatal). Does not deny fis_ok input set_update_sig,// when set, enables update_sig (and resets itself) input set_update_sig,// when set, enables update_sig (and resets itself) output pUpdateSig, // state variable output pUpdateSig, // state variable output reg sig_available, // device signature a ailable output reg sig_available, // device signature a ailable Loading @@ -74,13 +79,14 @@ module ahci_fis_receive#( output [7:0] tfd_sts, // Current PxTFD status field (updated after regFIS and SDB - certain fields) output [7:0] tfd_sts, // Current PxTFD status field (updated after regFIS and SDB - certain fields) // tfd_sts[7] - BSY, tfd_sts[4] - DRQ, tfd_sts[0] - ERR // tfd_sts[7] - BSY, tfd_sts[4] - DRQ, tfd_sts[0] - ERR output [7:0] tfd_err, // Current PxTFD error field (updated after regFIS and SDB) output [7:0] tfd_err, // Current PxTFD error field (updated after regFIS and SDB) output reg fis_i, // value of "I" field in received regsD2H or SDB FIS output reg fis_i, // value of "I" field in received regsD2H or SDB FIS or DMA Setup FIS output reg sdb_n, // value of "N" field in received SDB FIS output reg sdb_n, // value of "N" field in received SDB FIS output reg dma_a, // value of "A" field in received DMA Setup FIS output reg dma_a, // value of "A" field in received DMA Setup FIS output reg dma_d, // value of "D" field in received DMA Setup FIS output reg dma_d, // value of "D" field in received DMA Setup FIS output reg pio_i, // value of "I" field in received PIO Setup FIS output reg pio_i, // value of "I" field in received PIO Setup FIS output reg pio_d, // value of "D" field in received PIO Setup FIS output reg pio_d, // value of "D" field in received PIO Setup FIS output [7:0] pio_es, // value of PIO E_Status output [7:0] pio_es, // value of PIO E_Status output reg sactive0, // bit 0 of sActive DWORD received in SDB FIS // Using even word count (will be rounded up), partial DWORD (last) will be handled by PRD length if needed // Using even word count (will be rounded up), partial DWORD (last) will be handled by PRD length if needed output [31:2] xfer_cntr, // transfer counter in words for both DMA (31 bit) and PIO (lower 15 bits), updated after decr_dwc output [31:2] xfer_cntr, // transfer counter in words for both DMA (31 bit) and PIO (lower 15 bits), updated after decr_dwc output reg xfer_cntr_zero,// valid next cycle output reg xfer_cntr_zero,// valid next cycle Loading Loading @@ -144,6 +150,7 @@ localparam DATA_TYPE_ERR = 3; wire dma_in_start; wire dma_in_start; wire dma_in_stop; wire dma_in_stop; wire dma_skipping_extra; // skipping extra FIS data not needed for DMA reg dma_in; reg dma_in; reg [1:0] was_data_in; reg [1:0] was_data_in; reg [11:0] data_in_dwords_r; reg [11:0] data_in_dwords_r; Loading @@ -161,6 +168,7 @@ localparam DATA_TYPE_ERR = 3; reg is_data_fis; reg is_data_fis; wire is_FIS_HEAD = data_in_ready && (hba_data_in_type == DATA_TYPE_FIS_HEAD); wire is_FIS_HEAD = data_in_ready && (hba_data_in_type == DATA_TYPE_FIS_HEAD); wire is_FIS_NOT_HEAD = data_in_ready && (hba_data_in_type != DATA_TYPE_FIS_HEAD); wire data_in_ready = hba_data_in_valid && (hba_data_in_many || !(|was_data_in || hba_data_in_ready) ); wire data_in_ready = hba_data_in_valid && (hba_data_in_many || !(|was_data_in || hba_data_in_ready) ); Loading @@ -173,7 +181,7 @@ localparam DATA_TYPE_ERR = 3; reg [5:0] reg_ds; reg [5:0] reg_ds; reg [4:0] reg_ps; reg [4:0] reg_ps; reg reg_d2h; reg reg_d2h; reg reg_sdb; reg [1:0] reg_sdb; reg [31:2] xfer_cntr_r; reg [31:2] xfer_cntr_r; reg [31:2] prdbc_r; reg [31:2] prdbc_r; Loading @@ -192,15 +200,23 @@ localparam DATA_TYPE_ERR = 3; reg pUpdateSig_r = 1; // state variable reg pUpdateSig_r = 1; // state variable reg [31:0] sig_r; // signature register, save at reg [31:0] sig_r; // signature register, save at reg fis_extra_r; reg fis_first_invalid_r; reg fis_first_flushing_r; // Forward data to DMA (dev->mem) engine // Forward data to DMA (dev->mem) engine assign dma_in_valid = dma_in_ready && (hba_data_in_type == DATA_TYPE_DMA) && data_in_ready && !too_long_err; assign dma_in_valid = dma_in_ready && (hba_data_in_type == DATA_TYPE_DMA) && data_in_ready && !too_long_err; // Will also try to skip to the end of too long FIS assign dma_skipping_extra = (fis_extra_r || too_long_err) && (hba_data_in_type == DATA_TYPE_DMA) && data_in_ready ; assign dma_in_stop = dma_in && data_in_ready && (hba_data_in_type != DATA_TYPE_DMA); // || assign dma_in_stop = dma_in && data_in_ready && (hba_data_in_type != DATA_TYPE_DMA); // || assign reg_we_w = wreg_we_r && !dwords_over && fis_save; assign reg_we_w = wreg_we_r && !dwords_over && fis_save; assign dma_in_start = is_data_fis && wreg_we_r; assign dma_in_start = is_data_fis && wreg_we_r; assign hba_data_in_ready = dma_in_valid || wreg_we_r || fis_end_r[0]; assign hba_data_in_ready = dma_in_valid || dma_skipping_extra || wreg_we_r || fis_end_r[0] || (is_FIS_NOT_HEAD && fis_first_flushing_r); assign fis_ferr = too_long_err; assign fis_ferr = too_long_err; Loading @@ -214,6 +230,11 @@ localparam DATA_TYPE_ERR = 3; assign pio_es = pio_es_r; assign pio_es = pio_es_r; assign pUpdateSig = pUpdateSig_r; assign pUpdateSig = pUpdateSig_r; assign fis_extra = fis_extra_r; assign fis_first_invalid = fis_first_invalid_r; always @ (posedge mclk) begin always @ (posedge mclk) begin if (hba_rst || dma_in_stop) dma_in <= 0; if (hba_rst || dma_in_stop) dma_in <= 0; else if (dma_in_start) dma_in <= 1; else if (dma_in_start) dma_in <= 1; Loading @@ -228,6 +249,11 @@ localparam DATA_TYPE_ERR = 3; else if ((dma_in_valid && data_in_dwords_r[11]) || else if ((dma_in_valid && data_in_dwords_r[11]) || (wreg_we_r && dwords_over)) too_long_err <= 1; (wreg_we_r && dwords_over)) too_long_err <= 1; if (hba_rst || dma_in_start) fis_extra_r <= 0; else if (data_in_ready && (hba_data_in_type == DATA_TYPE_DMA) && dma_prds_done) fis_extra_r <= 1; if (get_fis) begin if (get_fis) begin reg_addr_r <= ({ADDRESS_BITS{get_dsfis}} & (FB_OFFS32 + DSFIS32)) | reg_addr_r <= ({ADDRESS_BITS{get_dsfis}} & (FB_OFFS32 + DSFIS32)) | ({ADDRESS_BITS{get_psfis}} & (FB_OFFS32 + PSFIS32)) | ({ADDRESS_BITS{get_psfis}} & (FB_OFFS32 + PSFIS32)) | Loading @@ -243,7 +269,7 @@ localparam DATA_TYPE_ERR = 3; ({4{get_ignore}} & IGNORE_LENM1 ); ({4{get_ignore}} & IGNORE_LENM1 ); // save signature FIS to memory if waiting (if not - ignore FIS) // save signature FIS to memory if waiting (if not - ignore FIS) // for non-signature /non-data - obey pcmd_fre // for non-signature /non-data - obey pcmd_fre fis_save <= (pUpdateSig_r || get_rfis) || (pcmd_fre && !get_data_fis && !get_ignore); fis_save <= (pUpdateSig_r && get_rfis) || (pcmd_fre && !get_data_fis && !get_ignore); is_data_fis <= get_data_fis; is_data_fis <= get_data_fis; store_sig <= (get_rfis)? 1 : 0; store_sig <= (get_rfis)? 1 : 0; Loading @@ -258,7 +284,7 @@ localparam DATA_TYPE_ERR = 3; reg_ds <= reg_ds << 1; reg_ds <= reg_ds << 1; reg_ps <= reg_ps << 1; reg_ps <= reg_ps << 1; reg_d2h <= 0; reg_d2h <= 0; reg_sdb <= 0; reg_sdb <= reg_sdb << 1; end end Loading Loading @@ -303,7 +329,7 @@ localparam DATA_TYPE_ERR = 3; // Updates PxTFD.STS.ERR with pPioErr[pPmpCur] ?? // Updates PxTFD.STS.ERR with pPioErr[pPmpCur] ?? else if (reg_ps[0]) tf_err_sts <= {hba_data_in[31:24],hba_data_in[23:16]}; else if (reg_ps[0]) tf_err_sts <= {hba_data_in[31:24],hba_data_in[23:16]}; else if (update_pio) tf_err_sts <= {pio_err_r, pio_es_r}; else if (update_pio) tf_err_sts <= {pio_err_r, pio_es_r}; else if (reg_sdb) tf_err_sts <= {hba_data_in[15:8], tf_err_sts[7], hba_data_in[6:4], tf_err_sts[3],hba_data_in[2:0]}; else if (reg_sdb[0]) tf_err_sts <= {hba_data_in[15:8], tf_err_sts[7], hba_data_in[6:4], tf_err_sts[3],hba_data_in[2:0]}; else if (clear_bsy_drq || set_bsy || clear_bsy_set_drq) else if (clear_bsy_drq || set_bsy || clear_bsy_set_drq) tf_err_sts <= tf_err_sts & {8'hff,clear_bsy_drq,3'h7,clear_bsy_drq,3'h7} | {8'h0,set_bsy,3'h0,clear_bsy_set_drq,3'h0}; tf_err_sts <= tf_err_sts & {8'hff,clear_bsy_drq,3'h7,clear_bsy_drq,3'h7} | {8'h0,set_bsy,3'h0,clear_bsy_set_drq,3'h0}; else if (set_sts_7f || set_sts_80) tf_err_sts <= {tf_err_sts[15:8],set_sts_80,{7{set_sts_7f}}} ; else if (set_sts_7f || set_sts_80) tf_err_sts <= {tf_err_sts[15:8],set_sts_80,{7{set_sts_7f}}} ; Loading @@ -315,7 +341,7 @@ localparam DATA_TYPE_ERR = 3; else if (update_sig_r) reg_addr <= PXSIG_OFFS32; else if (update_sig_r) reg_addr <= PXSIG_OFFS32; else if (update_prdbc_r) reg_addr <= CLB_OFFS32 + 1; // location of PRDBC else if (update_prdbc_r) reg_addr <= CLB_OFFS32 + 1; // location of PRDBC if (reg_d2h || reg_sdb || reg_ds[0]) fis_i <= hba_data_in[14]; if (reg_d2h || reg_sdb[0] || reg_ds[0]) fis_i <= hba_data_in[14]; if (reg_sdb) sdb_n <= hba_data_in[15]; if (reg_sdb) sdb_n <= hba_data_in[15]; if (reg_ds[0]) {dma_a,dma_d} <= {hba_data_in[15],hba_data_in[13]}; if (reg_ds[0]) {dma_a,dma_d} <= {hba_data_in[15],hba_data_in[13]}; Loading @@ -327,11 +353,13 @@ localparam DATA_TYPE_ERR = 3; if (hba_rst) pio_es_r <= 0; if (hba_rst) pio_es_r <= 0; else if (reg_ps[3]) pio_es_r <= hba_data_in[31:24]; else if (reg_ps[3]) pio_es_r <= hba_data_in[31:24]; if (hba_rst || reg_sdb || clear_xfer_cntr) xfer_cntr_r[31:2] <= 0; if (reg_sdb[1]) sactive0 <= hba_data_in[0]; if (hba_rst || reg_sdb[0] || clear_xfer_cntr) xfer_cntr_r[31:2] <= 0; else if (reg_ps[4] || reg_ds[5]) xfer_cntr_r[31:2] <= {reg_ds[5]?hba_data_in[31:16]:16'b0, hba_data_in[15:2]} + hba_data_in[1]; // round up else if (reg_ps[4] || reg_ds[5]) xfer_cntr_r[31:2] <= {reg_ds[5]?hba_data_in[31:16]:16'b0, hba_data_in[15:2]} + hba_data_in[1]; // round up else if (decr_dwc) xfer_cntr_r[31:2] <= {xfer_cntr_r[31:2]} - {18'b0, decr_DXC_dw[11:0]}; else if (decr_dwc) xfer_cntr_r[31:2] <= {xfer_cntr_r[31:2]} - {18'b0, decr_DXC_dw[11:0]}; if (hba_rst || reg_sdb || reg_ps[4] || reg_ds[5]) prdbc_r[31:2] <= 0; if (hba_rst || reg_sdb[0] || reg_ps[4] || reg_ds[5]) prdbc_r[31:2] <= 0; else if (decr_dwc) prdbc_r[31:2] <= {prdbc_r[31:2]} + {18'b0, decr_DXC_dw[11:0]}; else if (decr_dwc) prdbc_r[31:2] <= {prdbc_r[31:2]} + {18'b0, decr_DXC_dw[11:0]}; xfer_cntr_zero <= xfer_cntr_r[31:2] == 0; xfer_cntr_zero <= xfer_cntr_r[31:2] == 0; Loading @@ -352,6 +380,12 @@ localparam DATA_TYPE_ERR = 3; // Maybe it is not needed if the fsm will send this pulse? // Maybe it is not needed if the fsm will send this pulse? // data_in_words_apply <= dma_in_stop && (hba_data_in_type == DATA_TYPE_OK); // data_in_words_apply <= dma_in_stop && (hba_data_in_type == DATA_TYPE_OK); if (hba_rst || get_fis_busy_r) fis_first_invalid_r <= 0; else fis_first_invalid_r <= is_FIS_NOT_HEAD; if (!fis_first_invalid_r) fis_first_flushing_r <= 0; else if (fis_first_flush) fis_first_flushing_r <= 1; end end endmodule endmodule ahci/ahci_fis_transmit.v +1 −1 Original line number Original line Diff line number Diff line Loading @@ -75,7 +75,7 @@ module ahci_fis_transmit #( input dma_ct_busy, // dma module is busy reading command table from the system memory input dma_ct_busy, // dma module is busy reading command table from the system memory // issue dma_prd_start same time as dma_start if prefetch enabled, otherwise with cfis_xmit // issue dma_prd_start same time as dma_start if prefetch enabled, otherwise with cfis_xmit output reg dma_prd_start, // at or after cmd_start - enable reading PRD/data (if any) ch_prdtl should be valid, twice - OK output reg dma_prd_start, // at or after cmd_start - enable reading PRD/data (if any) ch_prdtl should be valid, twice - OK output reg dma_cmd_abort, // try to abort a command TODO: Implement output reg dma_cmd_abort, // try to abort a command // reading out command table data from DMA module // reading out command table data from DMA module output reg [ 4:0] ct_addr, // DWORD address output reg [ 4:0] ct_addr, // DWORD address Loading Loading
ahci/ahci_ctrl_stat.v +1 −1 Original line number Original line Diff line number Diff line Loading @@ -124,7 +124,7 @@ module ahci_ctrl_stat #( input ssts_det_ndnp, // no device detected, phy communication not established input ssts_det_ndnp, // no device detected, phy communication not established input ssts_det_dnp, // device detected, but phy communication not established input ssts_det_dnp, // device detected, but phy communication not established input ssts_det_dp, // device detected, phy communication established input ssts_det_dp, // device detected, phy communication established input ssts_det_offline, // device offline input ssts_det_offline, // device offline or BIST output [3:0] ssts_det, // current value of PxSSTS.DET output [3:0] ssts_det, // current value of PxSSTS.DET // SCR2:SControl (written by software only) // SCR2:SControl (written by software only) Loading
ahci/ahci_dma.v +33 −7 Original line number Original line Diff line number Diff line Loading @@ -65,11 +65,11 @@ module ahci_dma ( // After the first 0x80 bytes of the Command Table are read out, this module will read/process PRDs, // After the first 0x80 bytes of the Command Table are read out, this module will read/process PRDs, // not forwarding them to the output // not forwarding them to the output output prd_done, // prd done (regardless of the interrupt) - data transfer of one PRD is finished (any direction) output prd_done, // @mclk prd done (regardless of the interrupt) - data transfer of one PRD is finished (any direction) input prd_irq_clear, // reset pending prd_irq output prd_irq, // prd interrupt, if enabled output reg prd_irq_pend, // prd interrupt pending. This is just a condition for irq - actual will be generated after FIS OK output reg cmd_busy, // all commands output reg cmd_busy, // all commands output cmd_done, output cmd_done, // @ mclk // Data System memory -> HBA interface @ mclk // Data System memory -> HBA interface @ mclk output [31:0] sys_out, // 32-bit data from the system memory to HBA (dma data) output [31:0] sys_out, // 32-bit data from the system memory to HBA (dma data) Loading @@ -81,6 +81,8 @@ module ahci_dma ( output sys_nfull, // internal FIFO has room for more data (will decide - how big reserved space to keep) output sys_nfull, // internal FIFO has room for more data (will decide - how big reserved space to keep) input sys_we, input sys_we, output extra_din, // all DRDs are transferred to memory, but FIFO has some data. Valid when transfer is stopped // axi_hp signals write channel // axi_hp signals write channel // write address // write address output [31:0] afi_awaddr, output [31:0] afi_awaddr, Loading Loading @@ -228,8 +230,10 @@ module ahci_dma ( reg [3:0] dev_rd_id; reg [3:0] dev_rd_id; reg [5:0] afi_id; // common for 3 channels reg [5:0] afi_id; // common for 3 channels assign prd_done = done_dev_wr || done_dev_rd; wire fifo_nempty_mclk; assign prd_irq = data_irq && prd_done; reg en_extra_din_r; // assign prd_done = done_dev_wr || done_dev_rd; assign cmd_done_hclk = ((ct_busy_r==2'b10) && (prdtl_mclk == 0)) || done_flush || done_dev_rd; assign cmd_done_hclk = ((ct_busy_r==2'b10) && (prdtl_mclk == 0)) || done_flush || done_dev_rd; assign ct_done = (ct_busy_r == 2'b10); assign ct_done = (ct_busy_r == 2'b10); assign first_prd_fetch = ct_over_prd_enabled == 2'b01; assign first_prd_fetch = ct_over_prd_enabled == 2'b01; Loading Loading @@ -269,7 +273,7 @@ module ahci_dma ( assign afi_arburst = 2'h1; assign afi_arburst = 2'h1; assign afi_arqos = 4'h0; assign afi_arqos = 4'h0; assign afi_rdissuecap1en = 1'b0; assign afi_rdissuecap1en = 1'b0; assign extra_din = en_extra_din_r && fifo_nempty_mclk; always @ (posedge mclk) begin always @ (posedge mclk) begin if (ct_re) ct_data <= ct_data_ram[ct_addr]; if (ct_re) ct_data <= ct_data_ram[ct_addr]; if (ctba_ld) ctba_r <= ctba[31:7]; if (ctba_ld) ctba_r <= ctba[31:7]; Loading @@ -292,6 +296,13 @@ module ahci_dma ( prd_start_r <= prd_start; prd_start_r <= prd_start; if (mrst || prd_irq_clear ||cmd_start || cmd_abort) prd_irq_pend <= 0; else if (data_irq && prd_done) prd_irq_pend <= 1; if (mrst || cmd_start || cmd_abort) en_extra_din_r <= 0; else if (cmd_done) en_extra_din_r <= 1; end end Loading Loading @@ -472,6 +483,7 @@ module ahci_dma ( .dout_wstb (afi_wstb4), // output[3:0] reg .dout_wstb (afi_wstb4), // output[3:0] reg .done (done_dev_rd), // output reg .done (done_dev_rd), // output reg .busy (), // output .busy (), // output .fifo_nempty_mclk (fifo_nempty_mclk), // output reg .din (sys_in), // input[31:0] .din (sys_in), // input[31:0] .din_rdy (sys_nfull), // output .din_rdy (sys_nfull), // output .din_avail (sys_we) // input .din_avail (sys_we) // input Loading Loading @@ -535,5 +547,19 @@ module ahci_dma ( .busy() // output .busy() // output ); ); pulse_cross_clock #( .EXTRA_DLY(0) ) prd_done_mclk_i ( .rst (hrst), // input .src_clk (hclk), // input .dst_clk (mclk), // input .in_pulse (done_dev_wr || done_dev_rd), // input .out_pulse (prd_done), // output .busy() // output ); endmodule endmodule
ahci/ahci_dma_wr_fifo.v +3 −1 Original line number Original line Diff line number Diff line Loading @@ -59,7 +59,7 @@ module ahci_dma_wr_fifo#( // last_prd was not set // last_prd was not set output busy, output busy, // output done_flush, // finished last PRD (indicated by last_prd @ start), data left module // output done_flush, // finished last PRD (indicated by last_prd @ start), data left module output reg fifo_nempty_mclk, // to detect extra data from FIS, has some latency - only valid after read is stopped // mclk domain // mclk domain input [31:0] din, input [31:0] din, output din_rdy, // can accept data from HBA (multiple dwords, so reasonable latency is OK) output din_rdy, // can accept data from HBA (multiple dwords, so reasonable latency is OK) Loading Loading @@ -268,6 +268,8 @@ module ahci_dma_wr_fifo#( if (fifo_wr && !waddr[0]) fifo0_ram[waddr[ADDRESS_BITS:1]] <= din; if (fifo_wr && !waddr[0]) fifo0_ram[waddr[ADDRESS_BITS:1]] <= din; if (fifo_wr && waddr[0]) fifo1_ram[waddr[ADDRESS_BITS:1]] <= din; if (fifo_wr && waddr[0]) fifo1_ram[waddr[ADDRESS_BITS:1]] <= din; fifo_nempty_mclk <= (fifo_full [raddr[ADDRESS_BITS:1]] ^ raddr[ADDRESS_BITS]); // only valid after read is stopped end end Loading
ahci/ahci_fis_receive.v +52 −18 Original line number Original line Diff line number Diff line Loading @@ -36,6 +36,9 @@ module ahci_fis_receive#( input mclk, // for command/status input mclk, // for command/status // Control Interface // Control Interface output reg fis_first_vld, // fis_first contains valid FIS header, reset by get_* output reg fis_first_vld, // fis_first contains valid FIS header, reset by get_* // Debug features output fis_first_invalid, // Some data available from FIFO, but not FIS head input fis_first_flush, // Skip FIFO data until empty or FIS head // Receiving FIS // Receiving FIS input get_dsfis, input get_dsfis, input get_psfis, input get_psfis, Loading @@ -49,6 +52,8 @@ module ahci_fis_receive#( output reg fis_ok, // FIS done, checksum OK reset by starting a new get FIS output reg fis_ok, // FIS done, checksum OK reset by starting a new get FIS output reg fis_err, // FIS done, checksum ERROR reset by starting a new get FIS output reg fis_err, // FIS done, checksum ERROR reset by starting a new get FIS output fis_ferr, // FIS done, fatal error - FIS too long output fis_ferr, // FIS done, fatal error - FIS too long input dma_prds_done, // dma is done - check if FIS is done (some data may get stuck in dma FIFO - reported separately) output fis_extra, // all wanted data got, FIS may have extra data (non-fatal). Does not deny fis_ok input set_update_sig,// when set, enables update_sig (and resets itself) input set_update_sig,// when set, enables update_sig (and resets itself) output pUpdateSig, // state variable output pUpdateSig, // state variable output reg sig_available, // device signature a ailable output reg sig_available, // device signature a ailable Loading @@ -74,13 +79,14 @@ module ahci_fis_receive#( output [7:0] tfd_sts, // Current PxTFD status field (updated after regFIS and SDB - certain fields) output [7:0] tfd_sts, // Current PxTFD status field (updated after regFIS and SDB - certain fields) // tfd_sts[7] - BSY, tfd_sts[4] - DRQ, tfd_sts[0] - ERR // tfd_sts[7] - BSY, tfd_sts[4] - DRQ, tfd_sts[0] - ERR output [7:0] tfd_err, // Current PxTFD error field (updated after regFIS and SDB) output [7:0] tfd_err, // Current PxTFD error field (updated after regFIS and SDB) output reg fis_i, // value of "I" field in received regsD2H or SDB FIS output reg fis_i, // value of "I" field in received regsD2H or SDB FIS or DMA Setup FIS output reg sdb_n, // value of "N" field in received SDB FIS output reg sdb_n, // value of "N" field in received SDB FIS output reg dma_a, // value of "A" field in received DMA Setup FIS output reg dma_a, // value of "A" field in received DMA Setup FIS output reg dma_d, // value of "D" field in received DMA Setup FIS output reg dma_d, // value of "D" field in received DMA Setup FIS output reg pio_i, // value of "I" field in received PIO Setup FIS output reg pio_i, // value of "I" field in received PIO Setup FIS output reg pio_d, // value of "D" field in received PIO Setup FIS output reg pio_d, // value of "D" field in received PIO Setup FIS output [7:0] pio_es, // value of PIO E_Status output [7:0] pio_es, // value of PIO E_Status output reg sactive0, // bit 0 of sActive DWORD received in SDB FIS // Using even word count (will be rounded up), partial DWORD (last) will be handled by PRD length if needed // Using even word count (will be rounded up), partial DWORD (last) will be handled by PRD length if needed output [31:2] xfer_cntr, // transfer counter in words for both DMA (31 bit) and PIO (lower 15 bits), updated after decr_dwc output [31:2] xfer_cntr, // transfer counter in words for both DMA (31 bit) and PIO (lower 15 bits), updated after decr_dwc output reg xfer_cntr_zero,// valid next cycle output reg xfer_cntr_zero,// valid next cycle Loading Loading @@ -144,6 +150,7 @@ localparam DATA_TYPE_ERR = 3; wire dma_in_start; wire dma_in_start; wire dma_in_stop; wire dma_in_stop; wire dma_skipping_extra; // skipping extra FIS data not needed for DMA reg dma_in; reg dma_in; reg [1:0] was_data_in; reg [1:0] was_data_in; reg [11:0] data_in_dwords_r; reg [11:0] data_in_dwords_r; Loading @@ -161,6 +168,7 @@ localparam DATA_TYPE_ERR = 3; reg is_data_fis; reg is_data_fis; wire is_FIS_HEAD = data_in_ready && (hba_data_in_type == DATA_TYPE_FIS_HEAD); wire is_FIS_HEAD = data_in_ready && (hba_data_in_type == DATA_TYPE_FIS_HEAD); wire is_FIS_NOT_HEAD = data_in_ready && (hba_data_in_type != DATA_TYPE_FIS_HEAD); wire data_in_ready = hba_data_in_valid && (hba_data_in_many || !(|was_data_in || hba_data_in_ready) ); wire data_in_ready = hba_data_in_valid && (hba_data_in_many || !(|was_data_in || hba_data_in_ready) ); Loading @@ -173,7 +181,7 @@ localparam DATA_TYPE_ERR = 3; reg [5:0] reg_ds; reg [5:0] reg_ds; reg [4:0] reg_ps; reg [4:0] reg_ps; reg reg_d2h; reg reg_d2h; reg reg_sdb; reg [1:0] reg_sdb; reg [31:2] xfer_cntr_r; reg [31:2] xfer_cntr_r; reg [31:2] prdbc_r; reg [31:2] prdbc_r; Loading @@ -192,15 +200,23 @@ localparam DATA_TYPE_ERR = 3; reg pUpdateSig_r = 1; // state variable reg pUpdateSig_r = 1; // state variable reg [31:0] sig_r; // signature register, save at reg [31:0] sig_r; // signature register, save at reg fis_extra_r; reg fis_first_invalid_r; reg fis_first_flushing_r; // Forward data to DMA (dev->mem) engine // Forward data to DMA (dev->mem) engine assign dma_in_valid = dma_in_ready && (hba_data_in_type == DATA_TYPE_DMA) && data_in_ready && !too_long_err; assign dma_in_valid = dma_in_ready && (hba_data_in_type == DATA_TYPE_DMA) && data_in_ready && !too_long_err; // Will also try to skip to the end of too long FIS assign dma_skipping_extra = (fis_extra_r || too_long_err) && (hba_data_in_type == DATA_TYPE_DMA) && data_in_ready ; assign dma_in_stop = dma_in && data_in_ready && (hba_data_in_type != DATA_TYPE_DMA); // || assign dma_in_stop = dma_in && data_in_ready && (hba_data_in_type != DATA_TYPE_DMA); // || assign reg_we_w = wreg_we_r && !dwords_over && fis_save; assign reg_we_w = wreg_we_r && !dwords_over && fis_save; assign dma_in_start = is_data_fis && wreg_we_r; assign dma_in_start = is_data_fis && wreg_we_r; assign hba_data_in_ready = dma_in_valid || wreg_we_r || fis_end_r[0]; assign hba_data_in_ready = dma_in_valid || dma_skipping_extra || wreg_we_r || fis_end_r[0] || (is_FIS_NOT_HEAD && fis_first_flushing_r); assign fis_ferr = too_long_err; assign fis_ferr = too_long_err; Loading @@ -214,6 +230,11 @@ localparam DATA_TYPE_ERR = 3; assign pio_es = pio_es_r; assign pio_es = pio_es_r; assign pUpdateSig = pUpdateSig_r; assign pUpdateSig = pUpdateSig_r; assign fis_extra = fis_extra_r; assign fis_first_invalid = fis_first_invalid_r; always @ (posedge mclk) begin always @ (posedge mclk) begin if (hba_rst || dma_in_stop) dma_in <= 0; if (hba_rst || dma_in_stop) dma_in <= 0; else if (dma_in_start) dma_in <= 1; else if (dma_in_start) dma_in <= 1; Loading @@ -228,6 +249,11 @@ localparam DATA_TYPE_ERR = 3; else if ((dma_in_valid && data_in_dwords_r[11]) || else if ((dma_in_valid && data_in_dwords_r[11]) || (wreg_we_r && dwords_over)) too_long_err <= 1; (wreg_we_r && dwords_over)) too_long_err <= 1; if (hba_rst || dma_in_start) fis_extra_r <= 0; else if (data_in_ready && (hba_data_in_type == DATA_TYPE_DMA) && dma_prds_done) fis_extra_r <= 1; if (get_fis) begin if (get_fis) begin reg_addr_r <= ({ADDRESS_BITS{get_dsfis}} & (FB_OFFS32 + DSFIS32)) | reg_addr_r <= ({ADDRESS_BITS{get_dsfis}} & (FB_OFFS32 + DSFIS32)) | ({ADDRESS_BITS{get_psfis}} & (FB_OFFS32 + PSFIS32)) | ({ADDRESS_BITS{get_psfis}} & (FB_OFFS32 + PSFIS32)) | Loading @@ -243,7 +269,7 @@ localparam DATA_TYPE_ERR = 3; ({4{get_ignore}} & IGNORE_LENM1 ); ({4{get_ignore}} & IGNORE_LENM1 ); // save signature FIS to memory if waiting (if not - ignore FIS) // save signature FIS to memory if waiting (if not - ignore FIS) // for non-signature /non-data - obey pcmd_fre // for non-signature /non-data - obey pcmd_fre fis_save <= (pUpdateSig_r || get_rfis) || (pcmd_fre && !get_data_fis && !get_ignore); fis_save <= (pUpdateSig_r && get_rfis) || (pcmd_fre && !get_data_fis && !get_ignore); is_data_fis <= get_data_fis; is_data_fis <= get_data_fis; store_sig <= (get_rfis)? 1 : 0; store_sig <= (get_rfis)? 1 : 0; Loading @@ -258,7 +284,7 @@ localparam DATA_TYPE_ERR = 3; reg_ds <= reg_ds << 1; reg_ds <= reg_ds << 1; reg_ps <= reg_ps << 1; reg_ps <= reg_ps << 1; reg_d2h <= 0; reg_d2h <= 0; reg_sdb <= 0; reg_sdb <= reg_sdb << 1; end end Loading Loading @@ -303,7 +329,7 @@ localparam DATA_TYPE_ERR = 3; // Updates PxTFD.STS.ERR with pPioErr[pPmpCur] ?? // Updates PxTFD.STS.ERR with pPioErr[pPmpCur] ?? else if (reg_ps[0]) tf_err_sts <= {hba_data_in[31:24],hba_data_in[23:16]}; else if (reg_ps[0]) tf_err_sts <= {hba_data_in[31:24],hba_data_in[23:16]}; else if (update_pio) tf_err_sts <= {pio_err_r, pio_es_r}; else if (update_pio) tf_err_sts <= {pio_err_r, pio_es_r}; else if (reg_sdb) tf_err_sts <= {hba_data_in[15:8], tf_err_sts[7], hba_data_in[6:4], tf_err_sts[3],hba_data_in[2:0]}; else if (reg_sdb[0]) tf_err_sts <= {hba_data_in[15:8], tf_err_sts[7], hba_data_in[6:4], tf_err_sts[3],hba_data_in[2:0]}; else if (clear_bsy_drq || set_bsy || clear_bsy_set_drq) else if (clear_bsy_drq || set_bsy || clear_bsy_set_drq) tf_err_sts <= tf_err_sts & {8'hff,clear_bsy_drq,3'h7,clear_bsy_drq,3'h7} | {8'h0,set_bsy,3'h0,clear_bsy_set_drq,3'h0}; tf_err_sts <= tf_err_sts & {8'hff,clear_bsy_drq,3'h7,clear_bsy_drq,3'h7} | {8'h0,set_bsy,3'h0,clear_bsy_set_drq,3'h0}; else if (set_sts_7f || set_sts_80) tf_err_sts <= {tf_err_sts[15:8],set_sts_80,{7{set_sts_7f}}} ; else if (set_sts_7f || set_sts_80) tf_err_sts <= {tf_err_sts[15:8],set_sts_80,{7{set_sts_7f}}} ; Loading @@ -315,7 +341,7 @@ localparam DATA_TYPE_ERR = 3; else if (update_sig_r) reg_addr <= PXSIG_OFFS32; else if (update_sig_r) reg_addr <= PXSIG_OFFS32; else if (update_prdbc_r) reg_addr <= CLB_OFFS32 + 1; // location of PRDBC else if (update_prdbc_r) reg_addr <= CLB_OFFS32 + 1; // location of PRDBC if (reg_d2h || reg_sdb || reg_ds[0]) fis_i <= hba_data_in[14]; if (reg_d2h || reg_sdb[0] || reg_ds[0]) fis_i <= hba_data_in[14]; if (reg_sdb) sdb_n <= hba_data_in[15]; if (reg_sdb) sdb_n <= hba_data_in[15]; if (reg_ds[0]) {dma_a,dma_d} <= {hba_data_in[15],hba_data_in[13]}; if (reg_ds[0]) {dma_a,dma_d} <= {hba_data_in[15],hba_data_in[13]}; Loading @@ -327,11 +353,13 @@ localparam DATA_TYPE_ERR = 3; if (hba_rst) pio_es_r <= 0; if (hba_rst) pio_es_r <= 0; else if (reg_ps[3]) pio_es_r <= hba_data_in[31:24]; else if (reg_ps[3]) pio_es_r <= hba_data_in[31:24]; if (hba_rst || reg_sdb || clear_xfer_cntr) xfer_cntr_r[31:2] <= 0; if (reg_sdb[1]) sactive0 <= hba_data_in[0]; if (hba_rst || reg_sdb[0] || clear_xfer_cntr) xfer_cntr_r[31:2] <= 0; else if (reg_ps[4] || reg_ds[5]) xfer_cntr_r[31:2] <= {reg_ds[5]?hba_data_in[31:16]:16'b0, hba_data_in[15:2]} + hba_data_in[1]; // round up else if (reg_ps[4] || reg_ds[5]) xfer_cntr_r[31:2] <= {reg_ds[5]?hba_data_in[31:16]:16'b0, hba_data_in[15:2]} + hba_data_in[1]; // round up else if (decr_dwc) xfer_cntr_r[31:2] <= {xfer_cntr_r[31:2]} - {18'b0, decr_DXC_dw[11:0]}; else if (decr_dwc) xfer_cntr_r[31:2] <= {xfer_cntr_r[31:2]} - {18'b0, decr_DXC_dw[11:0]}; if (hba_rst || reg_sdb || reg_ps[4] || reg_ds[5]) prdbc_r[31:2] <= 0; if (hba_rst || reg_sdb[0] || reg_ps[4] || reg_ds[5]) prdbc_r[31:2] <= 0; else if (decr_dwc) prdbc_r[31:2] <= {prdbc_r[31:2]} + {18'b0, decr_DXC_dw[11:0]}; else if (decr_dwc) prdbc_r[31:2] <= {prdbc_r[31:2]} + {18'b0, decr_DXC_dw[11:0]}; xfer_cntr_zero <= xfer_cntr_r[31:2] == 0; xfer_cntr_zero <= xfer_cntr_r[31:2] == 0; Loading @@ -352,6 +380,12 @@ localparam DATA_TYPE_ERR = 3; // Maybe it is not needed if the fsm will send this pulse? // Maybe it is not needed if the fsm will send this pulse? // data_in_words_apply <= dma_in_stop && (hba_data_in_type == DATA_TYPE_OK); // data_in_words_apply <= dma_in_stop && (hba_data_in_type == DATA_TYPE_OK); if (hba_rst || get_fis_busy_r) fis_first_invalid_r <= 0; else fis_first_invalid_r <= is_FIS_NOT_HEAD; if (!fis_first_invalid_r) fis_first_flushing_r <= 0; else if (fis_first_flush) fis_first_flushing_r <= 1; end end endmodule endmodule
ahci/ahci_fis_transmit.v +1 −1 Original line number Original line Diff line number Diff line Loading @@ -75,7 +75,7 @@ module ahci_fis_transmit #( input dma_ct_busy, // dma module is busy reading command table from the system memory input dma_ct_busy, // dma module is busy reading command table from the system memory // issue dma_prd_start same time as dma_start if prefetch enabled, otherwise with cfis_xmit // issue dma_prd_start same time as dma_start if prefetch enabled, otherwise with cfis_xmit output reg dma_prd_start, // at or after cmd_start - enable reading PRD/data (if any) ch_prdtl should be valid, twice - OK output reg dma_prd_start, // at or after cmd_start - enable reading PRD/data (if any) ch_prdtl should be valid, twice - OK output reg dma_cmd_abort, // try to abort a command TODO: Implement output reg dma_cmd_abort, // try to abort a command // reading out command table data from DMA module // reading out command table data from DMA module output reg [ 4:0] ct_addr, // DWORD address output reg [ 4:0] ct_addr, // DWORD address Loading