Loading ahci/ahci_fis_receive.v +14 −10 Original line number Original line Diff line number Diff line Loading @@ -59,7 +59,7 @@ module ahci_fis_receive#( input set_sts_80, // set PxTFD.STS = 0x80 (may be combined with set_sts_7f), update input set_sts_80, // set PxTFD.STS = 0x80 (may be combined with set_sts_7f), update input decr_dwc, // decrement DMA Xfer counter // need pulse to 'update_prdbc' to write to registers input decr_dwc, // decrement DMA Xfer counter // need pulse to 'update_prdbc' to write to registers input [11:2] decr_DXC_dw, // decrement value (in DWORDs) input [11:0] decr_DXC_dw, // decrement value (in DWORDs) // TODO: Add writing PRDBC here? // TODO: Add writing PRDBC here? Loading @@ -76,6 +76,9 @@ module ahci_fis_receive#( // 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 output [11:0] data_in_dwords, // number of data dwords received (valid with 'done') // FSM will send this pulse // output reg data_in_words_apply, // apply data_in_words // Registers interface // Registers interface // 2. HBA R/W registers, may be added external register layer // 2. HBA R/W registers, may be added external register layer Loading Loading @@ -135,7 +138,7 @@ localparam DATA_TYPE_ERR = 3; wire dma_in_stop; wire dma_in_stop; reg dma_in; reg dma_in; reg [1:0] was_data_in; reg [1:0] was_data_in; reg [12:0] data_in_words; reg [11:0] data_in_dwords_r; reg dwords_over; reg dwords_over; reg too_long_err; reg too_long_err; Loading Loading @@ -189,6 +192,7 @@ localparam DATA_TYPE_ERR = 3; assign xfer_cntr = xfer_cntr_r[31:2]; assign xfer_cntr = xfer_cntr_r[31:2]; assign get_fis_busy = get_fis_busy_r; assign get_fis_busy = get_fis_busy_r; assign data_in_dwords = data_out_dwords_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; Loading @@ -197,11 +201,11 @@ localparam DATA_TYPE_ERR = 3; if (hba_rst) was_data_in <= 0; if (hba_rst) was_data_in <= 0; else was_data_in <= {was_data_in[0], hba_data_in_ready}; else was_data_in <= {was_data_in[0], hba_data_in_ready}; if (dma_in_start) data_in_words <= 0; if (dma_in_start) data_in_dwords_r <= 0; else if (dma_in_valid) data_in_words <= data_in_words + 1; else if (dma_in_valid) data_in_dwords_r <= data_in_dwords_r + 1; if (hba_rst) too_long_err <= 0; // it is a fatal error, only reset if (hba_rst) too_long_err <= 0; // it is a fatal error, only reset else if ((dma_in_valid && data_in_words[12]) || 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 (get_fis) begin if (get_fis) begin Loading Loading @@ -296,18 +300,18 @@ localparam DATA_TYPE_ERR = 3; if (hba_rst || reg_sdb) xfer_cntr_r[31:2] <= 0; if (hba_rst || reg_sdb) 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]} - {20'b0, decr_DXC_dw[11:2]}; 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 || reg_ps[4] || reg_ds[5]) prdbc_r[31:2] <= 0; else if (decr_dwc) prdbc_r[31:2] <= {prdbc_r[31:2]} + {20'b0, decr_DXC_dw[11:2]}; 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; update_err_sts_r <= update_err_sts || clear_bsy_drq || set_bsy || set_sts_7f || set_sts_80; update_err_sts_r <= update_err_sts || clear_bsy_drq || set_bsy || set_sts_7f || set_sts_80; update_prdbc_r <= update_prdbc; // same latency as update_err_sts update_prdbc_r <= update_prdbc; // same latency as update_err_sts // 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); end end endmodule endmodule ahci/ahci_fis_transmit.v +12 −8 Original line number Original line Diff line number Diff line Loading @@ -36,13 +36,15 @@ module ahci_fis_transmit #( input dx_transmit, // send FIS header DWORD, (just 0x46), then forward DMA data input dx_transmit, // send FIS header DWORD, (just 0x46), then forward DMA data // transmit until error, 2048DWords or pDmaXferCnt // transmit until error, 2048DWords or pDmaXferCnt input atapi_xmit, // tarsmit ATAPI command FIS input atapi_xmit, // tarsmit ATAPI command FIS output reg done, output reg done, output reg busy, output reg busy, input clearCmdToIssue, // From CFIS:SUCCESS input clearCmdToIssue, // From CFIS:SUCCESS output pCmdToIssue, // AHCI port variable output pCmdToIssue, // AHCI port variable // output dmaCntrZero, // DMA counter is zero - would be a duplicate to the one in receive module and dwords_sent output // output dmaCntrZero, // DMA counter is zero - would be a duplicate to the one in receive module and dwords_sent output output reg fetch_cmd_busy, // does not include prefetching CT // output reg fetch_cmd_busy, // does not include prefetching CT - now just use busy/done input syncesc_recv, // These two inputs interrupt transmit input syncesc_recv, // These two inputs interrupt transmit input xmit_err, // input xmit_err, // output [ 1:0] dx_err, // bit 0 - syncesc_recv, 1 - xmit_err (valid @ xmit_err and later, reset by new command) output [ 1:0] dx_err, // bit 0 - syncesc_recv, 1 - xmit_err (valid @ xmit_err and later, reset by new command) Loading @@ -56,7 +58,7 @@ module ahci_fis_transmit #( output ch_a, // ATAPI: 1 means device should send PIO setup FIS for ATAPI command output ch_a, // ATAPI: 1 means device should send PIO setup FIS for ATAPI command output [4:0] ch_cfl, // length of the command FIS in DW, 0 means none. 0 and 1 - illegal, output [4:0] ch_cfl, // length of the command FIS in DW, 0 means none. 0 and 1 - illegal, // maximal is 16 (0x10) // maximal is 16 (0x10) output reg [11:2] dwords_sent, // number of DWORDs transmitted (up to 2048) output reg [11:0] dwords_sent, // number of DWORDs transmitted (up to 2048) // register memory interface // register memory interface output reg [ADDRESS_BITS-1:0] reg_addr, output reg [ADDRESS_BITS-1:0] reg_addr, Loading Loading @@ -136,7 +138,7 @@ module ahci_fis_transmit #( reg acfis_xmit_busy_r; // reg acfis_xmit_busy_r; // // reg anc_fis_r; // This is ATAPI FIS, not Command FIS // reg anc_fis_r; // This is ATAPI FIS, not Command FIS wire acfis_xmit_start_w = (cfis_xmit || atapi_xmit || acfis_xmit_pend_r) && !dma_ct_busy && !fetch_cmd_busy; // dma_ct_busy no gaps with fetch_cmd_busy wire acfis_xmit_start_w = (cfis_xmit || atapi_xmit || acfis_xmit_pend_r) && !dma_ct_busy && !fetch_cmd_busy_r; // dma_ct_busy no gaps with fetch_cmd_busy wire acfis_xmit_end = ct_stb && fis_dw_last; wire acfis_xmit_end = ct_stb && fis_dw_last; wire ct_re_w; // next cycle will be ct_re; wire ct_re_w; // next cycle will be ct_re; Loading @@ -152,8 +154,10 @@ module ahci_fis_transmit #( reg dx_busy_r; reg dx_busy_r; reg [ 1:0] dx_err_r; reg [ 1:0] dx_err_r; wire any_cmd_start = fetch_cmd || cfis_xmit || dx_transmit || atapi_xmit; wire any_cmd_start = fetch_cmd || cfis_xmit || dx_transmit || atapi_xmit; wire done_w = dx_dma_last_w || ((|dx_err_r) && dx_busy_r) || chead_done_w || acfis_xmit_end; // done on last transmit or error wire done_w = dx_dma_last_w || ((|dx_err_r) && dx_busy_r) || chead_done_w || acfis_xmit_end || dma_start; // done on last transmit or error // dma_start ends 'fetch_cmd' reg fetch_cmd_busy_r; assign todev_valid = todev_full_r; assign todev_valid = todev_full_r; assign dma_re = dma_re_w; assign dma_re = dma_re_w; Loading Loading @@ -237,9 +241,9 @@ module ahci_fis_transmit #( else if (chead_done_w) pCmdToIssue_r <= 1; else if (chead_done_w) pCmdToIssue_r <= 1; else if (clearCmdToIssue) pCmdToIssue_r <= 0; else if (clearCmdToIssue) pCmdToIssue_r <= 0; if (hba_rst) fetch_cmd_busy <= 0; if (hba_rst) fetch_cmd_busy_r <= 0; else if (fetch_cmd) fetch_cmd_busy <= 1; else if (fetch_cmd) fetch_cmd_busy_r <= 1; else if (dma_start) fetch_cmd_busy <= 0; else if (dma_start) fetch_cmd_busy_r <= 0; //CFIS/ATAPI common //CFIS/ATAPI common Loading Loading @@ -280,7 +284,7 @@ module ahci_fis_transmit #( else if (dma_re_w) dx_dwords_left[11:2] <= dx_dwords_left[11:2] - 1; else if (dma_re_w) dx_dwords_left[11:2] <= dx_dwords_left[11:2] - 1; if (dx_transmit) dwords_sent <= 0; if (dx_transmit) dwords_sent <= 0; else if (dma_re_w) dwords_sent[11:2] <= dwords_sent[11:2] + 1; else if (dma_re_w) dwords_sent <= dwords_sent + 1; // send FIS header // send FIS header if (hba_rst || write_or_w) dx_fis_pend_r <= 0; if (hba_rst || write_or_w) dx_fis_pend_r <= 0; Loading ahci/ahci_fsm.v +14 −7 Original line number Original line Diff line number Diff line Loading @@ -43,11 +43,19 @@ module ahci_fsm #( // direct communication with transposrt, link and phy layers // direct communication with transposrt, link and phy layers input phy_ready, // goes up after comreset,cominit, align, ... input phy_ready, // goes up after comreset,cominit, align, ... output syncesc_send, // Send sync escape // Other signals.... // Other signals.... // inputs from the DMA engine input dma_prd_done, // output (finished next prd) input dma_prd_irq, // output (finished next prd and prd irq is enabled) input dma_cmd_busy, // output reg (DMA engine is processing PRDs) input dma_cmd_done, // output (last PRD is over) // Communication with ahci_fis_receive (some are unused // Communication with ahci_fis_receive (some are unused input fis_first_vld, // fis_first contains valid FIS header, reset by get_* input fis_first_vld, // fis_first contains valid FIS header, reset by 'get_*' input [7:0] fis_type, // FIS type (low byte in the first FIS DWORD), valid with 'fis_first_vld' // Receiving FIS // Receiving FIS output get_sig, // update signature output get_sig, // update signature output get_dsfis, output get_dsfis, Loading @@ -70,7 +78,7 @@ module ahci_fsm #( output set_sts_7f, // set PxTFD.STS = 0x7f, update output set_sts_7f, // set PxTFD.STS = 0x7f, update output set_sts_80, // set PxTFD.STS = 0x80 (may be combined with set_sts_7f), update output set_sts_80, // set PxTFD.STS = 0x80 (may be combined with set_sts_7f), update output decr_dwc, // decrement DMA Xfer counter // need pulse to 'update_prdbc' to write to registers output decr_dwc, // decrement DMA Xfer counter // need pulse to 'update_prdbc' to write to registers output [11:2] decr_DXC_dw, // decrement value (in DWORDs) output [11:0] decr_DXC_dw, // decrement value (in DWORDs) input [7:0] tfd_sts, // Current PxTFD status field (updated after regFIS and SDB - certain fields) input [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 input [7:0] tfd_err, // Current PxTFD error field (updated after regFIS and SDB) input [7:0] tfd_err, // Current PxTFD error field (updated after regFIS and SDB) Loading Loading @@ -99,9 +107,8 @@ module ahci_fsm #( output clearCmdToIssue, // From CFIS:SUCCESS output clearCmdToIssue, // From CFIS:SUCCESS input pCmdToIssue, // AHCI port variable input pCmdToIssue, // AHCI port variable // output dmaCntrZero, // DMA counter is zero - would be a duplicate to the one in receive module and dwords_sent output // output dmaCntrZero, // DMA counter is zero - would be a duplicate to the one in receive module and dwords_sent output input fetch_cmd_busy, // does not include prefetching CT // input syncesc_recv, // These two inputs interrupt transmit output syncesc_recv, // These two inputs interrupt transmit // input xmit_err, // output xmit_err, // input [ 1:0] dx_err, // bit 0 - syncesc_recv, 1 - xmit_err (valid @ xmit_err and later, reset by new command) input [ 1:0] dx_err, // bit 0 - syncesc_recv, 1 - xmit_err (valid @ xmit_err and later, reset by new command) input [15:0] ch_prdtl, // Physical region descriptor table length (in entries, 0 is 0) input [15:0] ch_prdtl, // Physical region descriptor table length (in entries, 0 is 0) Loading @@ -113,7 +120,7 @@ module ahci_fsm #( input ch_a, // ATAPI: 1 means device should send PIO setup FIS for ATAPI command input ch_a, // ATAPI: 1 means device should send PIO setup FIS for ATAPI command input [4:0] ch_cfl, // length of the command FIS in DW, 0 means none. 0 and 1 - illegal, input [4:0] ch_cfl, // length of the command FIS in DW, 0 means none. 0 and 1 - illegal, // maximal is 16 (0x10) // maximal is 16 (0x10) input [11:2] dwords_sent // number of DWORDs transmitted (up to 2048) input [11:0] dwords_sent // number of DWORDs transmitted (up to 2048) ); ); `include "includes/ahci_localparams.vh" // @SuppressThisWarning VEditor : Unused localparams `include "includes/ahci_localparams.vh" // @SuppressThisWarning VEditor : Unused localparams Loading ahci/ahci_top.v +240 −148 File changed.Preview size limit exceeded, changes collapsed. Show changes ahci/axi_ahci_regs.v +33 −1 Original line number Original line Diff line number Diff line Loading @@ -97,7 +97,14 @@ module axi_ahci_regs#( // input [3:0] hba_wstb, Needed? // input [3:0] hba_wstb, Needed? input [1:0] hba_re, // [0] - re, [1] - regen input [1:0] hba_re, // [0] - re, [1] - regen input [31:0] hba_din, input [31:0] hba_din, output [31:0] hba_dout output [31:0] hba_dout, // other control signals output reg [ 3:0] afi_wcache, output reg [ 3:0] afi_rcache, output afi_cache_set ); ); `include "includes/ahci_localparams.vh" // @SuppressThisWarning VEditor : Unused localparams `include "includes/ahci_localparams.vh" // @SuppressThisWarning VEditor : Unused localparams Loading @@ -109,6 +116,14 @@ module axi_ahci_regs#( localparam HBA_PORT__PxSCTL__DET__ADDR = 'h4b; localparam HBA_PORT__PxSCTL__DET__ADDR = 'h4b; localparam HBA_PORT__PxSCTL__DET__MASK = 'hf; localparam HBA_PORT__PxSCTL__DET__MASK = 'hf; localparam HBA_PORT__PxSCTL__DET__DFLT = 'h0; localparam HBA_PORT__PxSCTL__DET__DFLT = 'h0; // RW: SAXIHP write channel cache mode localparam HBA_PORT__AFI_CACHE__WR_CM__ADDR = 'h5c; localparam HBA_PORT__AFI_CACHE__WR_CM__MASK = 'hf0; localparam HBA_PORT__AFI_CACHE__WR_CM__DFLT = 'h30; // RW: SAXIHP read channel cache mode localparam HBA_PORT__AFI_CACHE__RD_CM__ADDR = 'h5c; localparam HBA_PORT__AFI_CACHE__RD_CM__MASK = 'hf; localparam HBA_PORT__AFI_CACHE__RD_CM__DFLT = 'h3; */ */ wire [ADDRESS_BITS-1:0] bram_waddr; wire [ADDRESS_BITS-1:0] bram_waddr; Loading Loading @@ -143,6 +158,8 @@ module axi_ahci_regs#( reg port_nrst_r; // port _reset by software reg port_nrst_r; // port _reset by software wire high_sel = bram_waddr_r[ADDRESS_BITS-1]; // high addresses - use single-cycle writes without read-modify-write wire high_sel = bram_waddr_r[ADDRESS_BITS-1]; // high addresses - use single-cycle writes without read-modify-write wire afi_cache_set_w = bram_wen_r && !high_sel && (bram_addr == HBA_PORT__AFI_CACHE__WR_CM__ADDR); // assign bram_addr = bram_ren[0] ? bram_raddr : (bram_wen ? bram_waddr : pre_awaddr); // assign bram_addr = bram_ren[0] ? bram_raddr : (bram_wen ? bram_waddr : pre_awaddr); assign bram_addr = bram_ren[0] ? bram_raddr : (bram_wen_r ? bram_waddr_r : bram_waddr); assign bram_addr = bram_ren[0] ? bram_raddr : (bram_wen_r ? bram_waddr_r : bram_waddr); assign hba_arst = !hba_nrst_r; // hba _reset (currently does ~ the same as port reset) assign hba_arst = !hba_nrst_r; // hba _reset (currently does ~ the same as port reset) Loading Loading @@ -196,6 +213,11 @@ module axi_ahci_regs#( port_nrst_r <= !ahci_regs_di[0]; // write "1" - reset on, write 0 - reset off port_nrst_r <= !ahci_regs_di[0]; // write "1" - reset on, write 0 - reset off end end always @(posedge aclk) begin if (arst) {afi_wcache,afi_rcache} <= 8'h33; else if (afi_cache_set_w) {afi_wcache,afi_rcache} <= ahci_regs_di[7:0]; end /* /* Will generate async reset on both HBA reset(for some time) and port reset (until released) Will generate async reset on both HBA reset(for some time) and port reset (until released) until it is more clear about GTX reset options. Such reset will be applied to both PLL and GTX, until it is more clear about GTX reset options. Such reset will be applied to both PLL and GTX, Loading Loading @@ -364,6 +386,16 @@ sata_phy_rst_out will be released after the sata clock is stable .half_empty () // output .half_empty () // output ); ); pulse_cross_clock #( .EXTRA_DLY(0) ) afi_cache_set_i ( .rst (arst), // input .src_clk (aclk), // input .dst_clk (hba_clk), // input .in_pulse (afi_cache_set_w), // input .out_pulse (afi_cache_set), // output .busy() // output ); endmodule endmodule Loading Loading
ahci/ahci_fis_receive.v +14 −10 Original line number Original line Diff line number Diff line Loading @@ -59,7 +59,7 @@ module ahci_fis_receive#( input set_sts_80, // set PxTFD.STS = 0x80 (may be combined with set_sts_7f), update input set_sts_80, // set PxTFD.STS = 0x80 (may be combined with set_sts_7f), update input decr_dwc, // decrement DMA Xfer counter // need pulse to 'update_prdbc' to write to registers input decr_dwc, // decrement DMA Xfer counter // need pulse to 'update_prdbc' to write to registers input [11:2] decr_DXC_dw, // decrement value (in DWORDs) input [11:0] decr_DXC_dw, // decrement value (in DWORDs) // TODO: Add writing PRDBC here? // TODO: Add writing PRDBC here? Loading @@ -76,6 +76,9 @@ module ahci_fis_receive#( // 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 output [11:0] data_in_dwords, // number of data dwords received (valid with 'done') // FSM will send this pulse // output reg data_in_words_apply, // apply data_in_words // Registers interface // Registers interface // 2. HBA R/W registers, may be added external register layer // 2. HBA R/W registers, may be added external register layer Loading Loading @@ -135,7 +138,7 @@ localparam DATA_TYPE_ERR = 3; wire dma_in_stop; wire dma_in_stop; reg dma_in; reg dma_in; reg [1:0] was_data_in; reg [1:0] was_data_in; reg [12:0] data_in_words; reg [11:0] data_in_dwords_r; reg dwords_over; reg dwords_over; reg too_long_err; reg too_long_err; Loading Loading @@ -189,6 +192,7 @@ localparam DATA_TYPE_ERR = 3; assign xfer_cntr = xfer_cntr_r[31:2]; assign xfer_cntr = xfer_cntr_r[31:2]; assign get_fis_busy = get_fis_busy_r; assign get_fis_busy = get_fis_busy_r; assign data_in_dwords = data_out_dwords_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; Loading @@ -197,11 +201,11 @@ localparam DATA_TYPE_ERR = 3; if (hba_rst) was_data_in <= 0; if (hba_rst) was_data_in <= 0; else was_data_in <= {was_data_in[0], hba_data_in_ready}; else was_data_in <= {was_data_in[0], hba_data_in_ready}; if (dma_in_start) data_in_words <= 0; if (dma_in_start) data_in_dwords_r <= 0; else if (dma_in_valid) data_in_words <= data_in_words + 1; else if (dma_in_valid) data_in_dwords_r <= data_in_dwords_r + 1; if (hba_rst) too_long_err <= 0; // it is a fatal error, only reset if (hba_rst) too_long_err <= 0; // it is a fatal error, only reset else if ((dma_in_valid && data_in_words[12]) || 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 (get_fis) begin if (get_fis) begin Loading Loading @@ -296,18 +300,18 @@ localparam DATA_TYPE_ERR = 3; if (hba_rst || reg_sdb) xfer_cntr_r[31:2] <= 0; if (hba_rst || reg_sdb) 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]} - {20'b0, decr_DXC_dw[11:2]}; 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 || reg_ps[4] || reg_ds[5]) prdbc_r[31:2] <= 0; else if (decr_dwc) prdbc_r[31:2] <= {prdbc_r[31:2]} + {20'b0, decr_DXC_dw[11:2]}; 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; update_err_sts_r <= update_err_sts || clear_bsy_drq || set_bsy || set_sts_7f || set_sts_80; update_err_sts_r <= update_err_sts || clear_bsy_drq || set_bsy || set_sts_7f || set_sts_80; update_prdbc_r <= update_prdbc; // same latency as update_err_sts update_prdbc_r <= update_prdbc; // same latency as update_err_sts // 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); end end endmodule endmodule
ahci/ahci_fis_transmit.v +12 −8 Original line number Original line Diff line number Diff line Loading @@ -36,13 +36,15 @@ module ahci_fis_transmit #( input dx_transmit, // send FIS header DWORD, (just 0x46), then forward DMA data input dx_transmit, // send FIS header DWORD, (just 0x46), then forward DMA data // transmit until error, 2048DWords or pDmaXferCnt // transmit until error, 2048DWords or pDmaXferCnt input atapi_xmit, // tarsmit ATAPI command FIS input atapi_xmit, // tarsmit ATAPI command FIS output reg done, output reg done, output reg busy, output reg busy, input clearCmdToIssue, // From CFIS:SUCCESS input clearCmdToIssue, // From CFIS:SUCCESS output pCmdToIssue, // AHCI port variable output pCmdToIssue, // AHCI port variable // output dmaCntrZero, // DMA counter is zero - would be a duplicate to the one in receive module and dwords_sent output // output dmaCntrZero, // DMA counter is zero - would be a duplicate to the one in receive module and dwords_sent output output reg fetch_cmd_busy, // does not include prefetching CT // output reg fetch_cmd_busy, // does not include prefetching CT - now just use busy/done input syncesc_recv, // These two inputs interrupt transmit input syncesc_recv, // These two inputs interrupt transmit input xmit_err, // input xmit_err, // output [ 1:0] dx_err, // bit 0 - syncesc_recv, 1 - xmit_err (valid @ xmit_err and later, reset by new command) output [ 1:0] dx_err, // bit 0 - syncesc_recv, 1 - xmit_err (valid @ xmit_err and later, reset by new command) Loading @@ -56,7 +58,7 @@ module ahci_fis_transmit #( output ch_a, // ATAPI: 1 means device should send PIO setup FIS for ATAPI command output ch_a, // ATAPI: 1 means device should send PIO setup FIS for ATAPI command output [4:0] ch_cfl, // length of the command FIS in DW, 0 means none. 0 and 1 - illegal, output [4:0] ch_cfl, // length of the command FIS in DW, 0 means none. 0 and 1 - illegal, // maximal is 16 (0x10) // maximal is 16 (0x10) output reg [11:2] dwords_sent, // number of DWORDs transmitted (up to 2048) output reg [11:0] dwords_sent, // number of DWORDs transmitted (up to 2048) // register memory interface // register memory interface output reg [ADDRESS_BITS-1:0] reg_addr, output reg [ADDRESS_BITS-1:0] reg_addr, Loading Loading @@ -136,7 +138,7 @@ module ahci_fis_transmit #( reg acfis_xmit_busy_r; // reg acfis_xmit_busy_r; // // reg anc_fis_r; // This is ATAPI FIS, not Command FIS // reg anc_fis_r; // This is ATAPI FIS, not Command FIS wire acfis_xmit_start_w = (cfis_xmit || atapi_xmit || acfis_xmit_pend_r) && !dma_ct_busy && !fetch_cmd_busy; // dma_ct_busy no gaps with fetch_cmd_busy wire acfis_xmit_start_w = (cfis_xmit || atapi_xmit || acfis_xmit_pend_r) && !dma_ct_busy && !fetch_cmd_busy_r; // dma_ct_busy no gaps with fetch_cmd_busy wire acfis_xmit_end = ct_stb && fis_dw_last; wire acfis_xmit_end = ct_stb && fis_dw_last; wire ct_re_w; // next cycle will be ct_re; wire ct_re_w; // next cycle will be ct_re; Loading @@ -152,8 +154,10 @@ module ahci_fis_transmit #( reg dx_busy_r; reg dx_busy_r; reg [ 1:0] dx_err_r; reg [ 1:0] dx_err_r; wire any_cmd_start = fetch_cmd || cfis_xmit || dx_transmit || atapi_xmit; wire any_cmd_start = fetch_cmd || cfis_xmit || dx_transmit || atapi_xmit; wire done_w = dx_dma_last_w || ((|dx_err_r) && dx_busy_r) || chead_done_w || acfis_xmit_end; // done on last transmit or error wire done_w = dx_dma_last_w || ((|dx_err_r) && dx_busy_r) || chead_done_w || acfis_xmit_end || dma_start; // done on last transmit or error // dma_start ends 'fetch_cmd' reg fetch_cmd_busy_r; assign todev_valid = todev_full_r; assign todev_valid = todev_full_r; assign dma_re = dma_re_w; assign dma_re = dma_re_w; Loading Loading @@ -237,9 +241,9 @@ module ahci_fis_transmit #( else if (chead_done_w) pCmdToIssue_r <= 1; else if (chead_done_w) pCmdToIssue_r <= 1; else if (clearCmdToIssue) pCmdToIssue_r <= 0; else if (clearCmdToIssue) pCmdToIssue_r <= 0; if (hba_rst) fetch_cmd_busy <= 0; if (hba_rst) fetch_cmd_busy_r <= 0; else if (fetch_cmd) fetch_cmd_busy <= 1; else if (fetch_cmd) fetch_cmd_busy_r <= 1; else if (dma_start) fetch_cmd_busy <= 0; else if (dma_start) fetch_cmd_busy_r <= 0; //CFIS/ATAPI common //CFIS/ATAPI common Loading Loading @@ -280,7 +284,7 @@ module ahci_fis_transmit #( else if (dma_re_w) dx_dwords_left[11:2] <= dx_dwords_left[11:2] - 1; else if (dma_re_w) dx_dwords_left[11:2] <= dx_dwords_left[11:2] - 1; if (dx_transmit) dwords_sent <= 0; if (dx_transmit) dwords_sent <= 0; else if (dma_re_w) dwords_sent[11:2] <= dwords_sent[11:2] + 1; else if (dma_re_w) dwords_sent <= dwords_sent + 1; // send FIS header // send FIS header if (hba_rst || write_or_w) dx_fis_pend_r <= 0; if (hba_rst || write_or_w) dx_fis_pend_r <= 0; Loading
ahci/ahci_fsm.v +14 −7 Original line number Original line Diff line number Diff line Loading @@ -43,11 +43,19 @@ module ahci_fsm #( // direct communication with transposrt, link and phy layers // direct communication with transposrt, link and phy layers input phy_ready, // goes up after comreset,cominit, align, ... input phy_ready, // goes up after comreset,cominit, align, ... output syncesc_send, // Send sync escape // Other signals.... // Other signals.... // inputs from the DMA engine input dma_prd_done, // output (finished next prd) input dma_prd_irq, // output (finished next prd and prd irq is enabled) input dma_cmd_busy, // output reg (DMA engine is processing PRDs) input dma_cmd_done, // output (last PRD is over) // Communication with ahci_fis_receive (some are unused // Communication with ahci_fis_receive (some are unused input fis_first_vld, // fis_first contains valid FIS header, reset by get_* input fis_first_vld, // fis_first contains valid FIS header, reset by 'get_*' input [7:0] fis_type, // FIS type (low byte in the first FIS DWORD), valid with 'fis_first_vld' // Receiving FIS // Receiving FIS output get_sig, // update signature output get_sig, // update signature output get_dsfis, output get_dsfis, Loading @@ -70,7 +78,7 @@ module ahci_fsm #( output set_sts_7f, // set PxTFD.STS = 0x7f, update output set_sts_7f, // set PxTFD.STS = 0x7f, update output set_sts_80, // set PxTFD.STS = 0x80 (may be combined with set_sts_7f), update output set_sts_80, // set PxTFD.STS = 0x80 (may be combined with set_sts_7f), update output decr_dwc, // decrement DMA Xfer counter // need pulse to 'update_prdbc' to write to registers output decr_dwc, // decrement DMA Xfer counter // need pulse to 'update_prdbc' to write to registers output [11:2] decr_DXC_dw, // decrement value (in DWORDs) output [11:0] decr_DXC_dw, // decrement value (in DWORDs) input [7:0] tfd_sts, // Current PxTFD status field (updated after regFIS and SDB - certain fields) input [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 input [7:0] tfd_err, // Current PxTFD error field (updated after regFIS and SDB) input [7:0] tfd_err, // Current PxTFD error field (updated after regFIS and SDB) Loading Loading @@ -99,9 +107,8 @@ module ahci_fsm #( output clearCmdToIssue, // From CFIS:SUCCESS output clearCmdToIssue, // From CFIS:SUCCESS input pCmdToIssue, // AHCI port variable input pCmdToIssue, // AHCI port variable // output dmaCntrZero, // DMA counter is zero - would be a duplicate to the one in receive module and dwords_sent output // output dmaCntrZero, // DMA counter is zero - would be a duplicate to the one in receive module and dwords_sent output input fetch_cmd_busy, // does not include prefetching CT // input syncesc_recv, // These two inputs interrupt transmit output syncesc_recv, // These two inputs interrupt transmit // input xmit_err, // output xmit_err, // input [ 1:0] dx_err, // bit 0 - syncesc_recv, 1 - xmit_err (valid @ xmit_err and later, reset by new command) input [ 1:0] dx_err, // bit 0 - syncesc_recv, 1 - xmit_err (valid @ xmit_err and later, reset by new command) input [15:0] ch_prdtl, // Physical region descriptor table length (in entries, 0 is 0) input [15:0] ch_prdtl, // Physical region descriptor table length (in entries, 0 is 0) Loading @@ -113,7 +120,7 @@ module ahci_fsm #( input ch_a, // ATAPI: 1 means device should send PIO setup FIS for ATAPI command input ch_a, // ATAPI: 1 means device should send PIO setup FIS for ATAPI command input [4:0] ch_cfl, // length of the command FIS in DW, 0 means none. 0 and 1 - illegal, input [4:0] ch_cfl, // length of the command FIS in DW, 0 means none. 0 and 1 - illegal, // maximal is 16 (0x10) // maximal is 16 (0x10) input [11:2] dwords_sent // number of DWORDs transmitted (up to 2048) input [11:0] dwords_sent // number of DWORDs transmitted (up to 2048) ); ); `include "includes/ahci_localparams.vh" // @SuppressThisWarning VEditor : Unused localparams `include "includes/ahci_localparams.vh" // @SuppressThisWarning VEditor : Unused localparams Loading
ahci/axi_ahci_regs.v +33 −1 Original line number Original line Diff line number Diff line Loading @@ -97,7 +97,14 @@ module axi_ahci_regs#( // input [3:0] hba_wstb, Needed? // input [3:0] hba_wstb, Needed? input [1:0] hba_re, // [0] - re, [1] - regen input [1:0] hba_re, // [0] - re, [1] - regen input [31:0] hba_din, input [31:0] hba_din, output [31:0] hba_dout output [31:0] hba_dout, // other control signals output reg [ 3:0] afi_wcache, output reg [ 3:0] afi_rcache, output afi_cache_set ); ); `include "includes/ahci_localparams.vh" // @SuppressThisWarning VEditor : Unused localparams `include "includes/ahci_localparams.vh" // @SuppressThisWarning VEditor : Unused localparams Loading @@ -109,6 +116,14 @@ module axi_ahci_regs#( localparam HBA_PORT__PxSCTL__DET__ADDR = 'h4b; localparam HBA_PORT__PxSCTL__DET__ADDR = 'h4b; localparam HBA_PORT__PxSCTL__DET__MASK = 'hf; localparam HBA_PORT__PxSCTL__DET__MASK = 'hf; localparam HBA_PORT__PxSCTL__DET__DFLT = 'h0; localparam HBA_PORT__PxSCTL__DET__DFLT = 'h0; // RW: SAXIHP write channel cache mode localparam HBA_PORT__AFI_CACHE__WR_CM__ADDR = 'h5c; localparam HBA_PORT__AFI_CACHE__WR_CM__MASK = 'hf0; localparam HBA_PORT__AFI_CACHE__WR_CM__DFLT = 'h30; // RW: SAXIHP read channel cache mode localparam HBA_PORT__AFI_CACHE__RD_CM__ADDR = 'h5c; localparam HBA_PORT__AFI_CACHE__RD_CM__MASK = 'hf; localparam HBA_PORT__AFI_CACHE__RD_CM__DFLT = 'h3; */ */ wire [ADDRESS_BITS-1:0] bram_waddr; wire [ADDRESS_BITS-1:0] bram_waddr; Loading Loading @@ -143,6 +158,8 @@ module axi_ahci_regs#( reg port_nrst_r; // port _reset by software reg port_nrst_r; // port _reset by software wire high_sel = bram_waddr_r[ADDRESS_BITS-1]; // high addresses - use single-cycle writes without read-modify-write wire high_sel = bram_waddr_r[ADDRESS_BITS-1]; // high addresses - use single-cycle writes without read-modify-write wire afi_cache_set_w = bram_wen_r && !high_sel && (bram_addr == HBA_PORT__AFI_CACHE__WR_CM__ADDR); // assign bram_addr = bram_ren[0] ? bram_raddr : (bram_wen ? bram_waddr : pre_awaddr); // assign bram_addr = bram_ren[0] ? bram_raddr : (bram_wen ? bram_waddr : pre_awaddr); assign bram_addr = bram_ren[0] ? bram_raddr : (bram_wen_r ? bram_waddr_r : bram_waddr); assign bram_addr = bram_ren[0] ? bram_raddr : (bram_wen_r ? bram_waddr_r : bram_waddr); assign hba_arst = !hba_nrst_r; // hba _reset (currently does ~ the same as port reset) assign hba_arst = !hba_nrst_r; // hba _reset (currently does ~ the same as port reset) Loading Loading @@ -196,6 +213,11 @@ module axi_ahci_regs#( port_nrst_r <= !ahci_regs_di[0]; // write "1" - reset on, write 0 - reset off port_nrst_r <= !ahci_regs_di[0]; // write "1" - reset on, write 0 - reset off end end always @(posedge aclk) begin if (arst) {afi_wcache,afi_rcache} <= 8'h33; else if (afi_cache_set_w) {afi_wcache,afi_rcache} <= ahci_regs_di[7:0]; end /* /* Will generate async reset on both HBA reset(for some time) and port reset (until released) Will generate async reset on both HBA reset(for some time) and port reset (until released) until it is more clear about GTX reset options. Such reset will be applied to both PLL and GTX, until it is more clear about GTX reset options. Such reset will be applied to both PLL and GTX, Loading Loading @@ -364,6 +386,16 @@ sata_phy_rst_out will be released after the sata clock is stable .half_empty () // output .half_empty () // output ); ); pulse_cross_clock #( .EXTRA_DLY(0) ) afi_cache_set_i ( .rst (arst), // input .src_clk (aclk), // input .dst_clk (hba_clk), // input .in_pulse (afi_cache_set_w), // input .out_pulse (afi_cache_set), // output .busy() // output ); endmodule endmodule Loading