Loading ahci/ahci_fis_receive.v +10 −6 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ module ahci_fis_receive#( input hba_rst, // @posedge mclk - sync reset input mclk, // for command/status // Control Interface output reg fis_first_vld, // fis_first contains valid FIS header, reset by get_* // Receiving FIS input get_sig, // update signature input get_dsfis, Loading @@ -44,8 +45,8 @@ module ahci_fis_receive#( input get_ufis, input get_data_fis, input get_ignore, // ignore whatever FIS (use for DMA activate too?) output reg get_fis_busy, // busy processing FIS output reg fis_first_vld, // fis_first contains valid FIS header, reset by get_* output get_fis_busy, // busy processing FIS output reg get_fis_done, // done processing FIS (see fis_ok, fis_err, fis_ferr) 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 fis_ferr, // FIS done, fatal error - FIS too long Loading Loading @@ -169,6 +170,7 @@ localparam DATA_TYPE_ERR = 3; reg [15:0] tf_err_sts; reg update_err_sts_r; reg update_prdbc_r; reg get_fis_busy_r; // 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; Loading @@ -186,7 +188,7 @@ localparam DATA_TYPE_ERR = 3; assign tfd_err = tf_err_sts[15:8]; assign xfer_cntr = xfer_cntr_r[31:2]; assign get_fis_busy = get_fis_busy_r; always @ (posedge mclk) begin if (hba_rst || dma_in_stop) dma_in <= 0; Loading Loading @@ -247,9 +249,11 @@ localparam DATA_TYPE_ERR = 3; fis_end_r <= {fis_end_r[0], fis_end_w}; if (hba_rst) get_fis_busy <= 0; else if (get_fis) get_fis_busy <= 1; else if (too_long_err || fis_end_w) get_fis_busy <= 0; if (hba_rst) get_fis_busy_r <= 0; else if (get_fis) get_fis_busy_r <= 1; else if (too_long_err || fis_end_w) get_fis_busy_r <= 0; get_fis_done <= get_fis_busy_r && (too_long_err || fis_end_w); if (hba_rst || get_fis) fis_first_vld <= 0; else if (is_FIS_HEAD) fis_first_vld <= 1; Loading ahci/ahci_fsm.v 0 → 100644 +126 −0 Original line number Diff line number Diff line /******************************************************************************* * Module: ahci_fsm * Date:2016-01-10 * Author: andrey * Description: AHCI host+port0 state machine * * Copyright (c) 2016 Elphel, Inc . * ahci_fsm.v is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * ahci_fsm.v is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/> . *******************************************************************************/ `timescale 1ns/1ps module ahci_fsm #( // parameter PREFETCH_ALWAYS = 0, parameter READ_REG_LATENCY = 2, // 0 if reg_rdata is available with reg_re/reg_addr, 2 with re/regen // parameter READ_CT_LATENCY = 1, // 0 if ct_rdata is available with reg_re/reg_addr, 2 with re/regen parameter ADDRESS_BITS = 10 // number of memory address bits - now fixed. Low half - RO/RW/RWC,RW1 (2-cycle write), 2-nd just RW (single-cycle) )( input hba_rst, // @posedge mclk input mclk, // for command/status // notification from axi_ahci_regs that software has written data to register input [ADDRESS_BITS-1:0] soft_write_addr, // register address written by software input [31:0] soft_write_data, // register data written (after applying wstb and type (RO, RW, RWC, RW1) input soft_write_en, // write enable for data write // input soft_arst, // reset SATA PHY not relying on SATA clock // R/W access to AXI/AHCI registers, shared with ahci_fis_receive and ahci_fis_transmit modules output [ADDRESS_BITS-1:0] regs_addr, output regs_we, // output [3:0] regs_wstb, Needed? output [1:0] regs_re, // [0] - re, [1] - regen output [31:0] regs_din, input [31:0] regs_dout, // direct communication with transposrt, link and phy layers input phy_ready, // goes up after comreset,cominit, align, ... // Other signals.... // Communication with ahci_fis_receive (some are unused input fis_first_vld, // fis_first contains valid FIS header, reset by get_* // Receiving FIS output get_sig, // update signature output get_dsfis, output get_psfis, output get_rfis, output get_sdbfis, output get_ufis, output get_data_fis, output get_ignore, // ignore whatever FIS (use for DMA activate too?) input get_fis_busy, // busy processing FIS input get_fis_done, // done processing FIS (see fis_ok, fis_err, fis_ferr) input fis_ok, // FIS done, checksum OK reset by starting a new get FIS input fis_err, // FIS done, checksum ERROR reset by starting a new get FIS input fis_ferr, // FIS done, fatal error - FIS too long // next commands use register address/data/we for 1 clock cycle - after next to command (commnd - t0, we - t2) output update_err_sts,// update PxTFD.STS and PxTFD.ERR from the last received regs d2h output update_prdbc, // update PRDBC in registers output clear_bsy_drq, // clear PxTFD.STS.BSY and PxTFD.STS.DRQ, update output set_bsy, // set PxTFD.STS.BSY, 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 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) 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 input [7:0] tfd_err, // Current PxTFD error field (updated after regFIS and SDB) input fis_i, // value of "I" field in received regsD2H or SDB FIS input sdb_n, // value of "N" field in received SDB FIS input dma_a, // value of "A" field in received DMA Setup FIS input dma_d, // value of "D" field in received DMA Setup FIS input pio_i, // value of "I" field in received PIO Setup FIS input pio_d, // value of "D" field in received PIO Setup FIS input [7:0] pio_es, // value of PIO E_Status // Using even word count (will be rounded up), partial DWORD (last) will be handled by PRD length if needed input [31:2] xfer_cntr, // transfer counter in words for both DMA (31 bit) and PIO (lower 15 bits), updated after decr_dwc input xfer_cntr_zero,// valid next cycle // Communication with ahci_fis_transmit // Command pulses to execute states output fetch_cmd, // Enter p:FetchCmd, fetch command header (from the register memory, prefetch command FIS) // wait for either fetch_cmd_busy == 0 or pCmdToIssue ==1 after fetch_cmd output cfis_xmit, // transmit command (wait for dma_ct_busy == 0) output dx_transmit, // send FIS header DWORD, (just 0x46), then forward DMA data // transmit until error, 2048DWords or pDmaXferCnt output atapi_xmit, // tarsmit ATAPI command FIS input done, input busy, output clearCmdToIssue, // From CFIS:SUCCESS 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 input fetch_cmd_busy, // does not include prefetching CT output syncesc_recv, // These two inputs interrupt transmit 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 [15:0] ch_prdtl, // Physical region descriptor table length (in entries, 0 is 0) input ch_c, // Clear busy upon R_OK for this FIS input ch_b, // Built-in self test command input ch_r, // reset - may need to send SYNC escape before this command input ch_p, // prefetchable - only used with non-zero PRDTL or ATAPI bit set input ch_w, // Write: system memory -> device 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, // maximal is 16 (0x10) input [11:2] dwords_sent // number of DWORDs transmitted (up to 2048) ); `include "includes/ahci_localparams.vh" // @SuppressThisWarning VEditor : Unused localparams /* Notes: Implement sync esc request/ackn in TL (available in LL) */ endmodule ahci/ahci_top.v +175 −87 Original line number Diff line number Diff line Loading @@ -29,7 +29,11 @@ module ahci_top#( input aclk, // clock - should be buffered input arst, // @aclk sync reset, active high input mclk, // SATA system clock (current 75MHz for SATA2) input mrst, // reset in mclk clock domain input mrst, // reset in mclk clock domain (after SATA PLL is on) // async reset for SATA (mrst will be responce to it) output hba_arst, // hba async reset (currently does ~ the same as port reset) output port_arst, // port0 async reset by software input hclk, // AXI HP interface clock for 64-bit DMA (current - 150MHz input hrst, // reset in hclk clock domain // MAXIGP1 Loading Loading @@ -143,17 +147,28 @@ module ahci_top#( wire [ADDRESS_BITS-1:0] soft_write_addr; // register address written by software wire [31:0] soft_write_data; // register data written (after applying wstb and type (RO, RW, RWC, RW1) wire soft_write_en; // write enable for data write wire soft_arst; // reset SATA PHY not relying on SATA clock // TODO: Decode from {bram_addr, ahci_regs_di}, bram_wen_d // wire hba_arst; // hba async reset (currently does ~ the same as port reset) // wire port_arst; // port0 async reset by software // 2. HBA R/W registers, use hba clock wire hba_rst; wire regs_we; wire [1:0] regs_re; // [0] - re, [1] - regen wire regs_we_fsm; wire [1:0] regs_re_fsm; wire [31:0] regs_din_from_fsm; // from fsm wire regs_we_freceive; wire [1:0] regs_re_ftransmit; // [0] - re, [1] - regen wire [ADDRESS_BITS-1:0] regs_faddr; // read/write adderss from ahci_fsm wire [ADDRESS_BITS-1:0] regs_waddr; wire [ADDRESS_BITS-1:0] regs_raddr; wire [31:0] regs_din; wire [31:0] regs_din_from_freceive; wire [31:0] regs_dout; wire [ADDRESS_BITS-1:0] regs_addr = ({ADDRESS_BITS{regs_we}} & regs_waddr) | ({ADDRESS_BITS{regs_re[0]}} & regs_raddr); wire [ADDRESS_BITS-1:0] regs_addr = ({ADDRESS_BITS{regs_we}} & regs_waddr) | ({ADDRESS_BITS{regs_re[0]}} & regs_raddr) | ({ADDRESS_BITS{regs_re_fsm[0] | regs_we_fsm}} & regs_faddr); wire [31:0] regs_din = ({32{regs_we_freceive}} & regs_din_from_freceive) | ({32{regs_we_fsm}} & regs_din_from_fsm); wire [1:0] regs_re = regs_re_ftransmit | regs_re_fsm; // [0] - re, [1] - regen wire regs_we = regs_we_freceive | regs_we_fsm; //--------------------- Loading @@ -179,9 +194,84 @@ module ahci_top#( wire [31:0] dma_dout; // output[31:0] wire dma_dav; // output wire dma_re; // input wire [31:0] d2h_data;// input[31:0] wire dma_in_ready; // output wire dma_we; // input // --------------------------------------- wire [31:0] xfer_cntr; wire xfer_cntr_zero; /* Instance template for module ahci_fsm */ ahci_fsm #( .READ_REG_LATENCY(2), .ADDRESS_BITS(10) ) ahci_fsm_i ( .hba_rst (hba_rst), // input .mclk (mclk), // input .soft_write_addr (soft_write_addr), // input[9:0] .soft_write_data (soft_write_data), // input[31:0] .soft_write_en (soft_write_en), // input .regs_addr (regs_faddr), // output[9:0] .regs_we (regs_we_fsm), // output .regs_re (regs_re_fsm), // output[1:0] .regs_din (regs_din_from_fsm), // output[31:0] .regs_dout (regs_dout), // input[31:0] .phy_ready(), // input .fis_first_vld(), // input .get_sig(), // output .get_dsfis(), // output .get_psfis(), // output .get_rfis(), // output .get_sdbfis(), // output .get_ufis(), // output .get_data_fis(), // output .get_ignore(), // output .get_fis_busy(), // input .get_fis_done(), // input .fis_ok(), // input .fis_err(), // input .fis_ferr(), // input .update_err_sts (), // output .update_prdbc(), // output .clear_bsy_drq(), // output .set_bsy(), // output .set_sts_7f(), // output .set_sts_80(), // output .decr_dwc(), // output .decr_DXC_dw(), // output[11:2] .tfd_sts(), // input[7:0] .tfd_err(), // input[7:0] .fis_i(), // input .sdb_n(), // input .dma_a(), // input .dma_d(), // input .pio_i(), // input .pio_d(), // input .pio_es(), // input[7:0] .xfer_cntr(), // input[31:2] .xfer_cntr_zero(), // input .fetch_cmd(), // output .cfis_xmit(), // output .dx_transmit(), // output .atapi_xmit(), // output .done(), // input .busy(), // input .clearCmdToIssue(), // output .pCmdToIssue(), // input .fetch_cmd_busy(), // input .syncesc_recv(), // output .xmit_err(), // output .dx_err(), // input[1:0] .ch_prdtl(), // input[15:0] .ch_c(), // input .ch_b(), // input .ch_r(), // input .ch_p(), // input .ch_w(), // input .ch_a(), // input .ch_cfl(), // input[4:0] .dwords_sent() // input[11:2] ); Loading Loading @@ -223,7 +313,8 @@ module ahci_top#( .soft_write_addr (soft_write_addr), // output[9:0] .soft_write_data (soft_write_data), // output[31:0] .soft_write_en (soft_write_en), // output .soft_arst (soft_arst), // output .hba_arst (hba_arst), // output .port_arst (port_arst), // output .hba_clk (mclk), // input .hba_rst (hba_rst), // input .hba_addr (regs_addr), // input[9:0] Loading Loading @@ -264,17 +355,7 @@ module ahci_top#( .sys_in (d2h_data), // input[31:0] .sys_nfull (dma_in_ready), // output .sys_we (dma_we), // input /* // xmit: DMA (memory -> device) interface input [31:0] dma_out, // 32-bit data from the DMA module, HBA -> device port input dma_dav, // at least one dword is ready to be read from DMA module output dma_re, // read dword from DMA module to the output register // rcv: Forwarding data to the DMA engine input dma_in_ready, // DMA engine ready to accept data output dma_in_valid // Write data to DMA dev->memory channel */ .afi_awaddr (afi_awaddr), // output[31:0] .afi_awvalid (afi_awvalid), // output .afi_awready (afi_awready), // input Loading Loading @@ -326,6 +407,9 @@ module ahci_top#( ) ahci_fis_receive_i ( .hba_rst (hba_rst), // input .mclk (mclk), // input .fis_first_vld (), // output reg .get_sig (), // input .get_dsfis (), // input .get_psfis (), // input Loading @@ -334,8 +418,9 @@ module ahci_top#( .get_ufis (), // input .get_data_fis (), // input .get_ignore (), // input .get_fis_busy (), // output reg .fis_first_vld (), // output reg .get_fis_done (), // output reg .fis_ok (), // output reg .fis_err (), // output reg .fis_ferr (), // output Loading @@ -356,18 +441,19 @@ module ahci_top#( .pio_i (), // output reg .pio_d (), // output reg .pio_es (), // output[7:0] reg .xfer_cntr (), // output[31:2] .xfer_cntr_zero (), // output reg .xfer_cntr (xfer_cntr[31:2]), // output[31:2] .xfer_cntr_zero (xfer_cntr_zero), // output reg .reg_addr (regs_waddr), // output[9:0] reg .reg_we (regs_we), // output reg .reg_data (regs_din), // output[31:0] reg .reg_we (regs_we_freceive), // output reg .reg_data (regs_din_from_freceive), // output[31:0] reg .hba_data_in (d2h_data), // input[31:0] .hba_data_in_type (d2h_type), // input[1:0] .hba_data_in_valid (d2h_valid), // input .hba_data_in_many (d2h_many), // input .hba_data_in_ready (d2h_ready), // output .dma_in_ready (), // input .dma_in_valid () // output .dma_in_ready (dma_in_ready), // input .dma_in_valid (dma_we) // output ); ahci_fis_transmit #( Loading @@ -378,10 +464,12 @@ module ahci_top#( ) ahci_fis_transmit_i ( .hba_rst (hba_rst), // input .mclk (mclk), // input .fetch_cmd (), // input .cfis_xmit (), // input .dx_transmit (), // input .atapi_xmit (), // input .done (), // output reg .busy (), // output reg .clearCmdToIssue (), // input Loading @@ -400,21 +488,21 @@ module ahci_top#( .ch_cfl (), // output[4:0] .dwords_sent (), // output[11:2] reg .reg_addr (regs_raddr), // output[9:0] reg .reg_re (regs_re), // output[1:0] .reg_re (regs_re_ftransmit), // output[1:0] .reg_rdata (regs_dout), // input[31:0] .xfer_cntr (), // input[31:2] .xfer_cntr (xfer_cntr[31:2]), // input[31:2] .dma_ctba_ld (ctba_ld), // output .dma_start (dma_cmd_start), // output .dma_dev_wr (), // output .dma_ct_busy (), // input .dma_dev_wr (dev_wr), // output .dma_ct_busy (dma_ct_busy), // input .dma_prd_start (dma_prd_start), // output reg .dma_cmd_abort (dma_cmd_abort), // output reg .ct_addr (dma_ct_addr), // output[4:0] reg .ct_re (dma_ct_re), // output[1:0] .ct_data (), // input[31:0] .dma_out (), // input[31:0] .dma_dav (), // input .dma_re (), // output .ct_data (dma_ct_data), // input[31:0] .dma_out (dma_dout), // input[31:0] .dma_dav (dma_dav), // input .dma_re (dma_re), // output .todev_data (h2d_data), // output[31:0] reg .todev_type (h2d_type), // output[1:0] reg .todev_valid (h2d_valid), // output Loading Loading
ahci/ahci_fis_receive.v +10 −6 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ module ahci_fis_receive#( input hba_rst, // @posedge mclk - sync reset input mclk, // for command/status // Control Interface output reg fis_first_vld, // fis_first contains valid FIS header, reset by get_* // Receiving FIS input get_sig, // update signature input get_dsfis, Loading @@ -44,8 +45,8 @@ module ahci_fis_receive#( input get_ufis, input get_data_fis, input get_ignore, // ignore whatever FIS (use for DMA activate too?) output reg get_fis_busy, // busy processing FIS output reg fis_first_vld, // fis_first contains valid FIS header, reset by get_* output get_fis_busy, // busy processing FIS output reg get_fis_done, // done processing FIS (see fis_ok, fis_err, fis_ferr) 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 fis_ferr, // FIS done, fatal error - FIS too long Loading Loading @@ -169,6 +170,7 @@ localparam DATA_TYPE_ERR = 3; reg [15:0] tf_err_sts; reg update_err_sts_r; reg update_prdbc_r; reg get_fis_busy_r; // 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; Loading @@ -186,7 +188,7 @@ localparam DATA_TYPE_ERR = 3; assign tfd_err = tf_err_sts[15:8]; assign xfer_cntr = xfer_cntr_r[31:2]; assign get_fis_busy = get_fis_busy_r; always @ (posedge mclk) begin if (hba_rst || dma_in_stop) dma_in <= 0; Loading Loading @@ -247,9 +249,11 @@ localparam DATA_TYPE_ERR = 3; fis_end_r <= {fis_end_r[0], fis_end_w}; if (hba_rst) get_fis_busy <= 0; else if (get_fis) get_fis_busy <= 1; else if (too_long_err || fis_end_w) get_fis_busy <= 0; if (hba_rst) get_fis_busy_r <= 0; else if (get_fis) get_fis_busy_r <= 1; else if (too_long_err || fis_end_w) get_fis_busy_r <= 0; get_fis_done <= get_fis_busy_r && (too_long_err || fis_end_w); if (hba_rst || get_fis) fis_first_vld <= 0; else if (is_FIS_HEAD) fis_first_vld <= 1; Loading
ahci/ahci_fsm.v 0 → 100644 +126 −0 Original line number Diff line number Diff line /******************************************************************************* * Module: ahci_fsm * Date:2016-01-10 * Author: andrey * Description: AHCI host+port0 state machine * * Copyright (c) 2016 Elphel, Inc . * ahci_fsm.v is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * ahci_fsm.v is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/> . *******************************************************************************/ `timescale 1ns/1ps module ahci_fsm #( // parameter PREFETCH_ALWAYS = 0, parameter READ_REG_LATENCY = 2, // 0 if reg_rdata is available with reg_re/reg_addr, 2 with re/regen // parameter READ_CT_LATENCY = 1, // 0 if ct_rdata is available with reg_re/reg_addr, 2 with re/regen parameter ADDRESS_BITS = 10 // number of memory address bits - now fixed. Low half - RO/RW/RWC,RW1 (2-cycle write), 2-nd just RW (single-cycle) )( input hba_rst, // @posedge mclk input mclk, // for command/status // notification from axi_ahci_regs that software has written data to register input [ADDRESS_BITS-1:0] soft_write_addr, // register address written by software input [31:0] soft_write_data, // register data written (after applying wstb and type (RO, RW, RWC, RW1) input soft_write_en, // write enable for data write // input soft_arst, // reset SATA PHY not relying on SATA clock // R/W access to AXI/AHCI registers, shared with ahci_fis_receive and ahci_fis_transmit modules output [ADDRESS_BITS-1:0] regs_addr, output regs_we, // output [3:0] regs_wstb, Needed? output [1:0] regs_re, // [0] - re, [1] - regen output [31:0] regs_din, input [31:0] regs_dout, // direct communication with transposrt, link and phy layers input phy_ready, // goes up after comreset,cominit, align, ... // Other signals.... // Communication with ahci_fis_receive (some are unused input fis_first_vld, // fis_first contains valid FIS header, reset by get_* // Receiving FIS output get_sig, // update signature output get_dsfis, output get_psfis, output get_rfis, output get_sdbfis, output get_ufis, output get_data_fis, output get_ignore, // ignore whatever FIS (use for DMA activate too?) input get_fis_busy, // busy processing FIS input get_fis_done, // done processing FIS (see fis_ok, fis_err, fis_ferr) input fis_ok, // FIS done, checksum OK reset by starting a new get FIS input fis_err, // FIS done, checksum ERROR reset by starting a new get FIS input fis_ferr, // FIS done, fatal error - FIS too long // next commands use register address/data/we for 1 clock cycle - after next to command (commnd - t0, we - t2) output update_err_sts,// update PxTFD.STS and PxTFD.ERR from the last received regs d2h output update_prdbc, // update PRDBC in registers output clear_bsy_drq, // clear PxTFD.STS.BSY and PxTFD.STS.DRQ, update output set_bsy, // set PxTFD.STS.BSY, 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 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) 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 input [7:0] tfd_err, // Current PxTFD error field (updated after regFIS and SDB) input fis_i, // value of "I" field in received regsD2H or SDB FIS input sdb_n, // value of "N" field in received SDB FIS input dma_a, // value of "A" field in received DMA Setup FIS input dma_d, // value of "D" field in received DMA Setup FIS input pio_i, // value of "I" field in received PIO Setup FIS input pio_d, // value of "D" field in received PIO Setup FIS input [7:0] pio_es, // value of PIO E_Status // Using even word count (will be rounded up), partial DWORD (last) will be handled by PRD length if needed input [31:2] xfer_cntr, // transfer counter in words for both DMA (31 bit) and PIO (lower 15 bits), updated after decr_dwc input xfer_cntr_zero,// valid next cycle // Communication with ahci_fis_transmit // Command pulses to execute states output fetch_cmd, // Enter p:FetchCmd, fetch command header (from the register memory, prefetch command FIS) // wait for either fetch_cmd_busy == 0 or pCmdToIssue ==1 after fetch_cmd output cfis_xmit, // transmit command (wait for dma_ct_busy == 0) output dx_transmit, // send FIS header DWORD, (just 0x46), then forward DMA data // transmit until error, 2048DWords or pDmaXferCnt output atapi_xmit, // tarsmit ATAPI command FIS input done, input busy, output clearCmdToIssue, // From CFIS:SUCCESS 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 input fetch_cmd_busy, // does not include prefetching CT output syncesc_recv, // These two inputs interrupt transmit 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 [15:0] ch_prdtl, // Physical region descriptor table length (in entries, 0 is 0) input ch_c, // Clear busy upon R_OK for this FIS input ch_b, // Built-in self test command input ch_r, // reset - may need to send SYNC escape before this command input ch_p, // prefetchable - only used with non-zero PRDTL or ATAPI bit set input ch_w, // Write: system memory -> device 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, // maximal is 16 (0x10) input [11:2] dwords_sent // number of DWORDs transmitted (up to 2048) ); `include "includes/ahci_localparams.vh" // @SuppressThisWarning VEditor : Unused localparams /* Notes: Implement sync esc request/ackn in TL (available in LL) */ endmodule
ahci/ahci_top.v +175 −87 Original line number Diff line number Diff line Loading @@ -29,7 +29,11 @@ module ahci_top#( input aclk, // clock - should be buffered input arst, // @aclk sync reset, active high input mclk, // SATA system clock (current 75MHz for SATA2) input mrst, // reset in mclk clock domain input mrst, // reset in mclk clock domain (after SATA PLL is on) // async reset for SATA (mrst will be responce to it) output hba_arst, // hba async reset (currently does ~ the same as port reset) output port_arst, // port0 async reset by software input hclk, // AXI HP interface clock for 64-bit DMA (current - 150MHz input hrst, // reset in hclk clock domain // MAXIGP1 Loading Loading @@ -143,17 +147,28 @@ module ahci_top#( wire [ADDRESS_BITS-1:0] soft_write_addr; // register address written by software wire [31:0] soft_write_data; // register data written (after applying wstb and type (RO, RW, RWC, RW1) wire soft_write_en; // write enable for data write wire soft_arst; // reset SATA PHY not relying on SATA clock // TODO: Decode from {bram_addr, ahci_regs_di}, bram_wen_d // wire hba_arst; // hba async reset (currently does ~ the same as port reset) // wire port_arst; // port0 async reset by software // 2. HBA R/W registers, use hba clock wire hba_rst; wire regs_we; wire [1:0] regs_re; // [0] - re, [1] - regen wire regs_we_fsm; wire [1:0] regs_re_fsm; wire [31:0] regs_din_from_fsm; // from fsm wire regs_we_freceive; wire [1:0] regs_re_ftransmit; // [0] - re, [1] - regen wire [ADDRESS_BITS-1:0] regs_faddr; // read/write adderss from ahci_fsm wire [ADDRESS_BITS-1:0] regs_waddr; wire [ADDRESS_BITS-1:0] regs_raddr; wire [31:0] regs_din; wire [31:0] regs_din_from_freceive; wire [31:0] regs_dout; wire [ADDRESS_BITS-1:0] regs_addr = ({ADDRESS_BITS{regs_we}} & regs_waddr) | ({ADDRESS_BITS{regs_re[0]}} & regs_raddr); wire [ADDRESS_BITS-1:0] regs_addr = ({ADDRESS_BITS{regs_we}} & regs_waddr) | ({ADDRESS_BITS{regs_re[0]}} & regs_raddr) | ({ADDRESS_BITS{regs_re_fsm[0] | regs_we_fsm}} & regs_faddr); wire [31:0] regs_din = ({32{regs_we_freceive}} & regs_din_from_freceive) | ({32{regs_we_fsm}} & regs_din_from_fsm); wire [1:0] regs_re = regs_re_ftransmit | regs_re_fsm; // [0] - re, [1] - regen wire regs_we = regs_we_freceive | regs_we_fsm; //--------------------- Loading @@ -179,9 +194,84 @@ module ahci_top#( wire [31:0] dma_dout; // output[31:0] wire dma_dav; // output wire dma_re; // input wire [31:0] d2h_data;// input[31:0] wire dma_in_ready; // output wire dma_we; // input // --------------------------------------- wire [31:0] xfer_cntr; wire xfer_cntr_zero; /* Instance template for module ahci_fsm */ ahci_fsm #( .READ_REG_LATENCY(2), .ADDRESS_BITS(10) ) ahci_fsm_i ( .hba_rst (hba_rst), // input .mclk (mclk), // input .soft_write_addr (soft_write_addr), // input[9:0] .soft_write_data (soft_write_data), // input[31:0] .soft_write_en (soft_write_en), // input .regs_addr (regs_faddr), // output[9:0] .regs_we (regs_we_fsm), // output .regs_re (regs_re_fsm), // output[1:0] .regs_din (regs_din_from_fsm), // output[31:0] .regs_dout (regs_dout), // input[31:0] .phy_ready(), // input .fis_first_vld(), // input .get_sig(), // output .get_dsfis(), // output .get_psfis(), // output .get_rfis(), // output .get_sdbfis(), // output .get_ufis(), // output .get_data_fis(), // output .get_ignore(), // output .get_fis_busy(), // input .get_fis_done(), // input .fis_ok(), // input .fis_err(), // input .fis_ferr(), // input .update_err_sts (), // output .update_prdbc(), // output .clear_bsy_drq(), // output .set_bsy(), // output .set_sts_7f(), // output .set_sts_80(), // output .decr_dwc(), // output .decr_DXC_dw(), // output[11:2] .tfd_sts(), // input[7:0] .tfd_err(), // input[7:0] .fis_i(), // input .sdb_n(), // input .dma_a(), // input .dma_d(), // input .pio_i(), // input .pio_d(), // input .pio_es(), // input[7:0] .xfer_cntr(), // input[31:2] .xfer_cntr_zero(), // input .fetch_cmd(), // output .cfis_xmit(), // output .dx_transmit(), // output .atapi_xmit(), // output .done(), // input .busy(), // input .clearCmdToIssue(), // output .pCmdToIssue(), // input .fetch_cmd_busy(), // input .syncesc_recv(), // output .xmit_err(), // output .dx_err(), // input[1:0] .ch_prdtl(), // input[15:0] .ch_c(), // input .ch_b(), // input .ch_r(), // input .ch_p(), // input .ch_w(), // input .ch_a(), // input .ch_cfl(), // input[4:0] .dwords_sent() // input[11:2] ); Loading Loading @@ -223,7 +313,8 @@ module ahci_top#( .soft_write_addr (soft_write_addr), // output[9:0] .soft_write_data (soft_write_data), // output[31:0] .soft_write_en (soft_write_en), // output .soft_arst (soft_arst), // output .hba_arst (hba_arst), // output .port_arst (port_arst), // output .hba_clk (mclk), // input .hba_rst (hba_rst), // input .hba_addr (regs_addr), // input[9:0] Loading Loading @@ -264,17 +355,7 @@ module ahci_top#( .sys_in (d2h_data), // input[31:0] .sys_nfull (dma_in_ready), // output .sys_we (dma_we), // input /* // xmit: DMA (memory -> device) interface input [31:0] dma_out, // 32-bit data from the DMA module, HBA -> device port input dma_dav, // at least one dword is ready to be read from DMA module output dma_re, // read dword from DMA module to the output register // rcv: Forwarding data to the DMA engine input dma_in_ready, // DMA engine ready to accept data output dma_in_valid // Write data to DMA dev->memory channel */ .afi_awaddr (afi_awaddr), // output[31:0] .afi_awvalid (afi_awvalid), // output .afi_awready (afi_awready), // input Loading Loading @@ -326,6 +407,9 @@ module ahci_top#( ) ahci_fis_receive_i ( .hba_rst (hba_rst), // input .mclk (mclk), // input .fis_first_vld (), // output reg .get_sig (), // input .get_dsfis (), // input .get_psfis (), // input Loading @@ -334,8 +418,9 @@ module ahci_top#( .get_ufis (), // input .get_data_fis (), // input .get_ignore (), // input .get_fis_busy (), // output reg .fis_first_vld (), // output reg .get_fis_done (), // output reg .fis_ok (), // output reg .fis_err (), // output reg .fis_ferr (), // output Loading @@ -356,18 +441,19 @@ module ahci_top#( .pio_i (), // output reg .pio_d (), // output reg .pio_es (), // output[7:0] reg .xfer_cntr (), // output[31:2] .xfer_cntr_zero (), // output reg .xfer_cntr (xfer_cntr[31:2]), // output[31:2] .xfer_cntr_zero (xfer_cntr_zero), // output reg .reg_addr (regs_waddr), // output[9:0] reg .reg_we (regs_we), // output reg .reg_data (regs_din), // output[31:0] reg .reg_we (regs_we_freceive), // output reg .reg_data (regs_din_from_freceive), // output[31:0] reg .hba_data_in (d2h_data), // input[31:0] .hba_data_in_type (d2h_type), // input[1:0] .hba_data_in_valid (d2h_valid), // input .hba_data_in_many (d2h_many), // input .hba_data_in_ready (d2h_ready), // output .dma_in_ready (), // input .dma_in_valid () // output .dma_in_ready (dma_in_ready), // input .dma_in_valid (dma_we) // output ); ahci_fis_transmit #( Loading @@ -378,10 +464,12 @@ module ahci_top#( ) ahci_fis_transmit_i ( .hba_rst (hba_rst), // input .mclk (mclk), // input .fetch_cmd (), // input .cfis_xmit (), // input .dx_transmit (), // input .atapi_xmit (), // input .done (), // output reg .busy (), // output reg .clearCmdToIssue (), // input Loading @@ -400,21 +488,21 @@ module ahci_top#( .ch_cfl (), // output[4:0] .dwords_sent (), // output[11:2] reg .reg_addr (regs_raddr), // output[9:0] reg .reg_re (regs_re), // output[1:0] .reg_re (regs_re_ftransmit), // output[1:0] .reg_rdata (regs_dout), // input[31:0] .xfer_cntr (), // input[31:2] .xfer_cntr (xfer_cntr[31:2]), // input[31:2] .dma_ctba_ld (ctba_ld), // output .dma_start (dma_cmd_start), // output .dma_dev_wr (), // output .dma_ct_busy (), // input .dma_dev_wr (dev_wr), // output .dma_ct_busy (dma_ct_busy), // input .dma_prd_start (dma_prd_start), // output reg .dma_cmd_abort (dma_cmd_abort), // output reg .ct_addr (dma_ct_addr), // output[4:0] reg .ct_re (dma_ct_re), // output[1:0] .ct_data (), // input[31:0] .dma_out (), // input[31:0] .dma_dav (), // input .dma_re (), // output .ct_data (dma_ct_data), // input[31:0] .dma_out (dma_dout), // input[31:0] .dma_dav (dma_dav), // input .dma_re (dma_re), // output .todev_data (h2d_data), // output[31:0] reg .todev_type (h2d_type), // output[1:0] reg .todev_valid (h2d_valid), // output Loading