Loading ahci/ahci_ctrl_stat.v +213 −39 Original line number Diff line number Diff line Loading @@ -46,18 +46,53 @@ module ahci_ctrl_stat #( input update_GHC__IS, input update_HBA_PORT__PxIS, input update_HBA_PORT__PxSSTS, input update_HBA_PORT__PxSERR, input update_HBA_PORT__PxCMD, // PxCMD input pcmd_clear_icc, // clear PxCMD.ICC field input pcmd_esp, // external SATA port (just forward value) output pcmd_cr, // command list run - current input pcmd_cr_set, // command list run set input pcmd_cr_reset, // command list run reset input pcmd_fr, // ahci_fis_receive:get_fis_busy input pcmd_clear_bsy_drq, // == ahci_fis_receive:clear_bsy_drq output pcmd_clo, //RW1, causes ahci_fis_receive:clear_bsy_drq, that in turn resets this bit input pcmd_clear_st, // RW clear ST (start) bit output pcmd_st, // current value //clear_bsy_drq // Interrupt inputs input sirq_TFE, // RWC: Task File Error Status input sirq_IF, // RWC: Interface Fatal Error Status (sect. 6.1.2) input sirq_INF, // RWC: Interface Non-Fatal Error Status (sect. 6.1.2) input sirq_OF, // RWC: Overflow Status input sirq_PRC, // RO: PhyRdy changed Status input sirq_PC, // RO: Port Connect Change Status input sirq_DP, // RWC: Descriptor Processed with "I" bit on input sirq_UF, // RO: Unknown FIS input sirq_SDB, // RWC: Set Device Bits Interrupt - Set Device bits FIS with 'I' bit set input sirq_DS, // RWC: DMA Setup FIS Interrupt - DMA Setup FIS received with 'I' bit set input sirq_PS, // RWC: PIO Setup FIS Interrupt - PIO Setup FIS received with 'I' bit set input sirq_DHR, // RWC: D2H Register FIS Interrupt - D2H Register FIS received with 'I' bit set // SCR1:SError (only inputs that are not available in sirq_* ones //sirq_PC, //sirq_UF input serr_DT, // RWC: Transport state transition error input serr_DS, // RWC: Link sequence error input serr_DH, // RWC: Handshake Error (i.e. Device got CRC error) input serr_DC, // RWC: CRC error in Link layer input serr_DB, // RWC: 10B to 8B decode error input serr_DW, // RWC: COMMWAKE signal was detected input serr_DI, // RWC: PHY Internal Error // sirq_PRC, // sirq_IF || // sirq_INF input serr_EP, // RWC: Protocol Error - a violation of SATA protocol detected input serr_EC, // RWC: Persistent Communication or Data Integrity Error input serr_ET, // RWC: Transient Data Integrity Error (error not recovered by the interface) input serr_EM, // RWC: Communication between the device and host was lost but re-established input serr_EI, // RWC: Recovered Data integrity Error // SCR0: SStatus input ssts_ipm_dnp, // device not present or communication not established Loading @@ -75,6 +110,13 @@ module ahci_ctrl_stat #( input ssts_det_dnp, // device detected, but phy communication not established input ssts_det_dp, // device detected, phy communication established input ssts_det_offline, // device detected, phy communication established // SCR2:SControl (written by software only) output reg [3:0] sctl_ipm, // Interface power management transitions allowed output reg [3:0] sctl_spd, // Interface maximal speed output reg [3:0] sctl_det, // Device detection initialization requested input pxci0_clear, // PxCI clear output pxci0, // pxCI current value /* */ Loading @@ -89,14 +131,14 @@ module ahci_ctrl_stat #( wire swr_HBA_PORT__PxIS = soft_write_en && (soft_write_addr == HBA_PORT__PxIS__CPDS__ADDR); wire swr_HBA_PORT__PxIE = soft_write_en && (soft_write_addr == HBA_PORT__PxIE__CPDE__ADDR); wire swr_HBA_PORT__PxSCTL = soft_write_en && (soft_write_addr == HBA_PORT__PxSCTL__SPD__ADDR); wire swr_HBA_PORT__PxSSTS = soft_write_en && (soft_write_addr == HBA_PORT__PxSSTS__SPD__ADDR); // wire swr_HBA_PORT__PxSSTS = soft_write_en && (soft_write_addr == HBA_PORT__PxSSTS__SPD__ADDR); wire swr_HBA_PORT__PxSERR = soft_write_en && (soft_write_addr == HBA_PORT__PxSERR__DIAG__X__ADDR); wire swr_HBA_PORT__PxCI = soft_write_en && (soft_write_addr == HBA_PORT__PxCI__CI__DFLT); reg hba_rst_r = 1; reg rst_por; reg rst_hba; reg rst_port; reg rst_hba; // @SuppressThisWarning VEditor : Unused, maybe will be used later reg rst_port; // @SuppressThisWarning VEditor : Unused, maybe will be used later reg ghc_ie_r; reg ghc_is_r; Loading @@ -104,16 +146,43 @@ module ahci_ctrl_stat #( reg [31:0] PxIE_r; // some bits will be unused by PxIS_MASK reg [31:0] PxIS_r; // some bits will be unused by PxIS_MASK reg [11:0] PxSSTS_r; reg [31:0] PxSERR_r; // Assuming it is not needed for HBA, just for the software reg [31:0] PxCMD_r; reg pxci0_r; wire [31:0] sirq = {32{sirq_TFE}} & HBA_PORT__PxIS__TFES__MASK | // 'h40000000; {32{sirq_IF }} & HBA_PORT__PxIS__IFS__MASK | // 'h8000000; {32{sirq_INF}} & HBA_PORT__PxIS__INFS__MASK | // 'h4000000; {32{sirq_OF }} & HBA_PORT__PxIS__OFS__MASK | // 'h1000000; {32{sirq_PRC}} & HBA_PORT__PxIS__PRCS__MASK | // 'h400000; {32{sirq_PC}} & HBA_PORT__PxIS__PCS__MASK | // 'h40;; {32{sirq_DP}} & HBA_PORT__PxIS__DPS__MASK | // 'h20; {32{sirq_UF }} & HBA_PORT__PxIS__UFS__MASK | // 'h10; {32{sirq_SDB}} & HBA_PORT__PxIS__SDBS__MASK | // 'h8; {32{sirq_DS }} & HBA_PORT__PxIS__DSS__MASK | // 'h4; {32{sirq_PS }} & HBA_PORT__PxIS__PSS__MASK | // 'h2; {32{sirq_DHR}} & HBA_PORT__PxIS__DHRS__MASK; // 'h1; wire [31:0] serr = {32{sirq_PC}} & HBA_PORT__PxSERR__DIAG__X__MASK | // 'h4000000; {32{sirq_UF }} & HBA_PORT__PxSERR__DIAG__F__MASK | // 'h2000000; {32{serr_DT }} & HBA_PORT__PxSERR__DIAG__T__MASK | // 'h1000000; {32{serr_DS }} & HBA_PORT__PxSERR__DIAG__S__MASK | // 'h800000; {32{serr_DH }} & HBA_PORT__PxSERR__DIAG__H__MASK | // 'h400000; {32{serr_DC }} & HBA_PORT__PxSERR__DIAG__C__MASK | // 'h200000; {32{serr_DB }} & HBA_PORT__PxSERR__DIAG__B__MASK | // 'h80000; {32{serr_DW }} & HBA_PORT__PxSERR__DIAG__W__MASK | // 'h40000; {32{serr_DI }} & HBA_PORT__PxSERR__DIAG__I__MASK | // 'h20000; {32{sirq_PRC}} & HBA_PORT__PxSERR__DIAG__N__MASK | // 'h10000; {32{sirq_IF | sirq_INF }} & HBA_PORT__PxSERR__ERR__E__MASK | // 'h800; {32{serr_EP }} & HBA_PORT__PxSERR__ERR__P__MASK | // 'h400; {32{serr_EC }} & HBA_PORT__PxSERR__ERR__C__MASK | // 'h200; {32{serr_ET }} & HBA_PORT__PxSERR__ERR__T__MASK | // 'h100; {32{serr_EM }} & HBA_PORT__PxSERR__ERR__M__MASK | // 'h2; {32{serr_EI }} & HBA_PORT__PxSERR__ERR__I__MASK; // 'h0; wire [11:8] sssts_ipm = ({4{ssts_ipm_active}} & 4'h1) | ({4{ssts_ipm_part}} & 4'h2) | ({4{ssts_ipm_slumb}} & 4'h6) | Loading @@ -136,6 +205,7 @@ localparam PxIE_MASK = HBA_PORT__PxIE__TFEE__MASK | // 'h40000000; HBA_PORT__PxIE__DSE__MASK | // 'h4; HBA_PORT__PxIE__PSE__MASK | // 'h2; HBA_PORT__PxIE__DHRE__MASK; // 'h1; localparam PxIS_MASK = HBA_PORT__PxIS__TFES__MASK | // 'h40000000; HBA_PORT__PxIS__IFS__MASK | // 'h8000000; HBA_PORT__PxIS__INFS__MASK | // 'h4000000; Loading @@ -147,6 +217,76 @@ localparam PxIS_MASK = HBA_PORT__PxIS__TFES__MASK | // 'h40000000; HBA_PORT__PxIS__PSS__MASK | // 'h2; HBA_PORT__PxIS__DHRS__MASK; // 'h1; localparam PxSERR_MASK = HBA_PORT__PxSERR__DIAG__X__MASK | // 'h4000000; HBA_PORT__PxSERR__DIAG__F__MASK | // 'h2000000; HBA_PORT__PxSERR__DIAG__T__MASK | // 'h1000000; HBA_PORT__PxSERR__DIAG__S__MASK | // 'h800000; HBA_PORT__PxSERR__DIAG__H__MASK | // 'h400000; HBA_PORT__PxSERR__DIAG__C__MASK | // 'h200000; HBA_PORT__PxSERR__DIAG__B__MASK | // 'h80000; HBA_PORT__PxSERR__DIAG__W__MASK | // 'h40000; HBA_PORT__PxSERR__DIAG__I__MASK | // 'h20000; HBA_PORT__PxSERR__DIAG__N__MASK | // 'h10000; HBA_PORT__PxSERR__ERR__E__MASK | // 'h800; HBA_PORT__PxSERR__ERR__P__MASK | // 'h400; HBA_PORT__PxSERR__ERR__C__MASK | // 'h200; HBA_PORT__PxSERR__ERR__T__MASK | // 'h100; HBA_PORT__PxSERR__ERR__M__MASK | // 'h2; HBA_PORT__PxSERR__ERR__I__MASK; // 'h0; localparam PxCMD_DFLT = HBA_PORT__PxCMD__ICC__DFLT | // 'h0; HBA_PORT__PxCMD__ASP__DFLT | // 'h0; HBA_PORT__PxCMD__ALPE__DFLT | // 'h0; HBA_PORT__PxCMD__DLAE__DFLT | // 'h0; HBA_PORT__PxCMD__ATAPI__DFLT | // 'h0; HBA_PORT__PxCMD__APSTE__DFLT | // 'h0; HBA_PORT__PxCMD__FBSCP__DFLT | // 'h0; HBA_PORT__PxCMD__ESP__DFLT | // 'h200000; HBA_PORT__PxCMD__CPD__DFLT | // 'h0; HBA_PORT__PxCMD__MPSP__DFLT | // 'h0; HBA_PORT__PxCMD__HPCP__DFLT | // 'h40000; HBA_PORT__PxCMD__PMA__DFLT | // 'h0; HBA_PORT__PxCMD__CPS__DFLT | // 'h0; HBA_PORT__PxCMD__CR__DFLT | // 'h0; HBA_PORT__PxCMD__FR__DFLT | // 'h0; HBA_PORT__PxCMD__MPSS__DFLT | // 'h0; HBA_PORT__PxCMD__CCS__DFLT | // 'h0; HBA_PORT__PxCMD__FRE__DFLT | // 'h0; HBA_PORT__PxCMD__CLO__DFLT | // 'h0; HBA_PORT__PxCMD__POD__DFLT | // 'h4; HBA_PORT__PxCMD__SUD__DFLT | // 'h2; HBA_PORT__PxCMD__ST__DFLT; // 'h0; localparam PxCMD_MASK = HBA_PORT__PxCMD__ICC__MASK | // 'hf0000000; // HBA_PORT__PxCMD__ASP__MASK | // 'h8000000; // HBA_PORT__PxCMD__ALPE__MASK | // 'h4000000; // HBA_PORT__PxCMD__DLAE__MASK | // 'h2000000; // HBA_PORT__PxCMD__ATAPI__MASK | // 'h1000000; // HBA_PORT__PxCMD__APSTE__MASK | // 'h800000; // HBA_PORT__PxCMD__FBSCP__MASK | // 'h400000; HBA_PORT__PxCMD__ESP__MASK | // 'h200000; // HBA_PORT__PxCMD__CPD__MASK | // 'h100000; // HBA_PORT__PxCMD__MPSP__MASK | // 'h80000; // HBA_PORT__PxCMD__HPCP__MASK | // 'h40000; // HBA_PORT__PxCMD__PMA__MASK | // 'h20000; // HBA_PORT__PxCMD__CPS__MASK | // 'h10000; HBA_PORT__PxCMD__CR__MASK | // 'h8000; HBA_PORT__PxCMD__FR__MASK | // 'h4000; // HBA_PORT__PxCMD__MPSS__MASK | // 'h2000; // HBA_PORT__PxCMD__CCS__MASK | // 'h1f00; HBA_PORT__PxCMD__FRE__MASK | // 'h10; HBA_PORT__PxCMD__CLO__MASK | // 'h8; // HBA_PORT__PxCMD__POD__MASK | // 'h4; // HBA_PORT__PxCMD__SUD__MASK | // 'h2; HBA_PORT__PxCMD__ST__MASK; // 'h1; assign pxci0 = pxci0_r; assign pcmd_cr = PxCMD_r[15]; // command list run - current assign pcmd_clo = PxCMD_r[3]; // causes ahci_fis_receive:clear_bsy_drq, that in turn resets this bit assign pcmd_st = PxCMD_r[0]; // current value always @(posedge mclk) begin if (mrst) irq <= 0; Loading Loading @@ -187,40 +327,74 @@ localparam PxIS_MASK = HBA_PORT__PxIS__TFES__MASK | // 'h40000000; else PxIS_r <= PxIS_MASK & ((swr_HBA_PORT__PxIS ? soft_write_data : PxIS_r) | sirq); end // HBA_PORT__PxIE register always @(posedge mclk) begin if (rst_por) set_ghc_is_r <= 0; // TODO: Not exactly clear - when ghc_is_r should be set after being RWC? After setting some not masked new individual interrupt? else set_ghc_is_r <= |(sirq & PxIE_r); end // HBA_PORT__PxSSTS register - updated from the HOST only always @(posedge mclk) begin if (mrst) PxSSTS_r[11:8] <= 0; else if (ssts_ipm_dnp || ssts_ipm_active || ssts_ipm_part || ssts_ipm_slumb || ssts_ipm_devsleep) PxSSTS_r[11:8] <= sssts_ipm[11:8]; if (mrst) PxSSTS_r[ 7:4] <= 0; else if (ssts_ipm_dnp || ssts_ipm_active || ssts_ipm_part || ssts_ipm_slumb || ssts_ipm_devsleep) PxSSTS_r[ 7:4] <= sssts_spd[ 7:4]; else if (ssts_spd_dnp || ssts_spd_gen1 || ssts_spd_gen2|| ssts_spd_gen3) PxSSTS_r[ 7:4] <= sssts_spd[ 7:4]; if (mrst) PxSSTS_r[ 3:0] <= 0; else if (ssts_ipm_dnp || ssts_ipm_active || ssts_ipm_part || ssts_ipm_slumb || ssts_ipm_devsleep) PxSSTS_r[ 3:0] <= sssts_det[ 3:0]; else if (ssts_det_ndnp || ssts_det_dnp || ssts_det_dp || ssts_det_offline) PxSSTS_r[ 3:0] <= sssts_det[ 3:0]; end // HBA_PORT__PxSCTL register - updated by the software only always @ (posedge mclk) begin if (rst_por) {sctl_ipm, sctl_spd, sctl_det} <= 0; else if (swr_HBA_PORT__PxSCTL) {sctl_ipm, sctl_spd, sctl_det} <= soft_write_data [11:0]; end // HBA_PORT__PxSERR register always @(posedge mclk) begin if (rst_por) PxSERR_r <= 0; else PxSERR_r <= PxSERR_MASK & ((swr_HBA_PORT__PxSERR ? soft_write_data : PxSERR_r) | serr); end // HBA_PORT__PxCI[0] register - cleared by HBA, set by software always @(posedge mclk) begin if (mrst || pxci0_clear) pxci0_r <= 0; else if (swr_HBA_PORT__PxCI) pxci0_r <= soft_write_data[0]; end // HBA_PORT__PxCMD register - different behavious of differtnt fields // use PxCMD_MASK to prevent generation of unneeded register bits always @(posedge mclk) begin if (mrst) PxCMD_r <= PxCMD_DFLT; else PxCMD_r <= (~PxCMD_MASK & PxCMD_DFLT ) | (PxCMD_MASK & ( swr_HBA_PORT__PxCMD? soft_write_data : ( (pcmd_clear_icc ? 0 : (PxCMD_r & HBA_PORT__PxCMD__ICC__MASK)) | (pcmd_esp ? HBA_PORT__PxCMD__ESP__MASK : 0) | (pcmd_cr_reset ? 0 : (HBA_PORT__PxCMD__CR__MASK & (pcmd_cr_set? (~0):(PxCMD_r)))) | (pcmd_fr? HBA_PORT__PxCMD__FR__MASK : 0 ) | (HBA_PORT__PxCMD__FRE__MASK & PxCMD_r) | // no HBA control (pcmd_clear_bsy_drq ? 0 : (PxCMD_r & HBA_PORT__PxCMD__CLO__MASK)) | (pcmd_clear_st ? 0 : (PxCMD_r & HBA_PORT__PxCMD__ST__MASK)) ))); end // Update AXI registers with the current local data always @ (posedge mclk) begin regs_addr <= ({ADDRESS_BITS{update_GHC__IS}} & GHC__IS__IPS__ADDR) | ({ADDRESS_BITS{update_HBA_PORT__PxIS}} & HBA_PORT__PxIS__CPDS__ADDR) | // TODO: add more ... ({ADDRESS_BITS{update_HBA_PORT__PxSSTS}} & HBA_PORT__PxSSTS__SPD__ADDR) ; ({ADDRESS_BITS{update_HBA_PORT__PxIS}} & HBA_PORT__PxIS__CPDS__ADDR) | ({ADDRESS_BITS{update_HBA_PORT__PxSSTS}} & HBA_PORT__PxSSTS__SPD__ADDR) | ({ADDRESS_BITS{update_HBA_PORT__PxSERR}} & HBA_PORT__PxSERR__DIAG__X__ADDR) | ({ADDRESS_BITS{update_HBA_PORT__PxCMD}} & HBA_PORT__PxCMD__ICC__ADDR); regs_din <= ({32{update_GHC__IS}} & {31'b0, ghc_is_r}) | ({32{update_HBA_PORT__PxIS}} & PxIS_r) | // TODO: add more ... ({32{update_HBA_PORT__PxSSTS}} &{20'b0, PxSSTS_r[11:0]}); // | // TODO: add more ... ({32{update_HBA_PORT__PxIS}} & PxIS_r) | ({32{update_HBA_PORT__PxSSTS}} & {20'b0, PxSSTS_r[11:0]}) | ({32{update_HBA_PORT__PxSERR}} & PxSERR_r) | ({32{update_HBA_PORT__PxCMD}} & PxCMD_r); regs_we <= update_GHC__IS || update_HBA_PORT__PxIS || update_HBA_PORT__PxSSTS; regs_we <= update_GHC__IS || update_HBA_PORT__PxIS || update_HBA_PORT__PxSSTS || update_HBA_PORT__PxSERR | update_HBA_PORT__PxCMD; end // /* sirq */ endmodule ahci/ahci_top.v +73 −0 Original line number Diff line number Diff line Loading @@ -426,6 +426,79 @@ module ahci_top#( ); /* Instance template for module ahci_ctrl_stat */ ahci_ctrl_stat #( .ADDRESS_BITS (ADDRESS_BITS) ) ahci_ctrl_stat_i ( .mrst (), // input .mclk (), // input .was_hba_rst (), // input .was_port_rst (), // input .soft_write_addr (), // input[9:0] .soft_write_data (), // input[31:0] .soft_write_en (), // input .regs_addr (), // output[9:0] reg .regs_we (), // output reg .regs_din (), // output[31:0] reg .update_GHC__IS (), // input .update_HBA_PORT__PxIS (), // input .update_HBA_PORT__PxSSTS (), // input .update_HBA_PORT__PxSERR (), // input .update_HBA_PORT__PxCMD (), // input .pcmd_clear_icc (), // input .pcmd_esp (), // input .pcmd_cr (), // output .pcmd_cr_set (), // input .pcmd_cr_reset (), // input .pcmd_fr (), // input .pcmd_clear_bsy_drq (), // input .pcmd_clo (), // output .pcmd_clear_st (), // input .pcmd_st (), // output .sirq_TFE (), // input .sirq_IF (), // input .sirq_INF (), // input .sirq_OF (), // input .sirq_PRC (), // input .sirq_PC (), // input .sirq_DP (), // input .sirq_UF (), // input .sirq_SDB (), // input .sirq_DS (), // input .sirq_PS (), // input .sirq_DHR (), // input .serr_DT (), // input .serr_DS (), // input .serr_DH (), // input .serr_DC (), // input .serr_DB (), // input .serr_DW (), // input .serr_DI (), // input .serr_EP (), // input .serr_EC (), // input .serr_ET (), // input .serr_EM (), // input .serr_EI (), // input .ssts_ipm_dnp (), // input .ssts_ipm_active (), // input .ssts_ipm_part (), // input .ssts_ipm_slumb (), // input .ssts_ipm_devsleep (), // input .ssts_spd_dnp (), // input .ssts_spd_gen1 (), // input .ssts_spd_gen2 (), // input .ssts_spd_gen3 (), // input .ssts_det_ndnp (), // input .ssts_det_dnp (), // input .ssts_det_dp (), // input .ssts_det_offline (), // input .sctl_ipm (), // output[3:0] reg .sctl_spd (), // output[3:0] reg .sctl_det (), // output[3:0] reg .pxci0_clear (), // input .pxci0 (), // output .irq () // output reg ); ahci_dma ahci_dma_i ( .mrst (mrst), // input Loading Loading
ahci/ahci_ctrl_stat.v +213 −39 Original line number Diff line number Diff line Loading @@ -46,18 +46,53 @@ module ahci_ctrl_stat #( input update_GHC__IS, input update_HBA_PORT__PxIS, input update_HBA_PORT__PxSSTS, input update_HBA_PORT__PxSERR, input update_HBA_PORT__PxCMD, // PxCMD input pcmd_clear_icc, // clear PxCMD.ICC field input pcmd_esp, // external SATA port (just forward value) output pcmd_cr, // command list run - current input pcmd_cr_set, // command list run set input pcmd_cr_reset, // command list run reset input pcmd_fr, // ahci_fis_receive:get_fis_busy input pcmd_clear_bsy_drq, // == ahci_fis_receive:clear_bsy_drq output pcmd_clo, //RW1, causes ahci_fis_receive:clear_bsy_drq, that in turn resets this bit input pcmd_clear_st, // RW clear ST (start) bit output pcmd_st, // current value //clear_bsy_drq // Interrupt inputs input sirq_TFE, // RWC: Task File Error Status input sirq_IF, // RWC: Interface Fatal Error Status (sect. 6.1.2) input sirq_INF, // RWC: Interface Non-Fatal Error Status (sect. 6.1.2) input sirq_OF, // RWC: Overflow Status input sirq_PRC, // RO: PhyRdy changed Status input sirq_PC, // RO: Port Connect Change Status input sirq_DP, // RWC: Descriptor Processed with "I" bit on input sirq_UF, // RO: Unknown FIS input sirq_SDB, // RWC: Set Device Bits Interrupt - Set Device bits FIS with 'I' bit set input sirq_DS, // RWC: DMA Setup FIS Interrupt - DMA Setup FIS received with 'I' bit set input sirq_PS, // RWC: PIO Setup FIS Interrupt - PIO Setup FIS received with 'I' bit set input sirq_DHR, // RWC: D2H Register FIS Interrupt - D2H Register FIS received with 'I' bit set // SCR1:SError (only inputs that are not available in sirq_* ones //sirq_PC, //sirq_UF input serr_DT, // RWC: Transport state transition error input serr_DS, // RWC: Link sequence error input serr_DH, // RWC: Handshake Error (i.e. Device got CRC error) input serr_DC, // RWC: CRC error in Link layer input serr_DB, // RWC: 10B to 8B decode error input serr_DW, // RWC: COMMWAKE signal was detected input serr_DI, // RWC: PHY Internal Error // sirq_PRC, // sirq_IF || // sirq_INF input serr_EP, // RWC: Protocol Error - a violation of SATA protocol detected input serr_EC, // RWC: Persistent Communication or Data Integrity Error input serr_ET, // RWC: Transient Data Integrity Error (error not recovered by the interface) input serr_EM, // RWC: Communication between the device and host was lost but re-established input serr_EI, // RWC: Recovered Data integrity Error // SCR0: SStatus input ssts_ipm_dnp, // device not present or communication not established Loading @@ -75,6 +110,13 @@ module ahci_ctrl_stat #( input ssts_det_dnp, // device detected, but phy communication not established input ssts_det_dp, // device detected, phy communication established input ssts_det_offline, // device detected, phy communication established // SCR2:SControl (written by software only) output reg [3:0] sctl_ipm, // Interface power management transitions allowed output reg [3:0] sctl_spd, // Interface maximal speed output reg [3:0] sctl_det, // Device detection initialization requested input pxci0_clear, // PxCI clear output pxci0, // pxCI current value /* */ Loading @@ -89,14 +131,14 @@ module ahci_ctrl_stat #( wire swr_HBA_PORT__PxIS = soft_write_en && (soft_write_addr == HBA_PORT__PxIS__CPDS__ADDR); wire swr_HBA_PORT__PxIE = soft_write_en && (soft_write_addr == HBA_PORT__PxIE__CPDE__ADDR); wire swr_HBA_PORT__PxSCTL = soft_write_en && (soft_write_addr == HBA_PORT__PxSCTL__SPD__ADDR); wire swr_HBA_PORT__PxSSTS = soft_write_en && (soft_write_addr == HBA_PORT__PxSSTS__SPD__ADDR); // wire swr_HBA_PORT__PxSSTS = soft_write_en && (soft_write_addr == HBA_PORT__PxSSTS__SPD__ADDR); wire swr_HBA_PORT__PxSERR = soft_write_en && (soft_write_addr == HBA_PORT__PxSERR__DIAG__X__ADDR); wire swr_HBA_PORT__PxCI = soft_write_en && (soft_write_addr == HBA_PORT__PxCI__CI__DFLT); reg hba_rst_r = 1; reg rst_por; reg rst_hba; reg rst_port; reg rst_hba; // @SuppressThisWarning VEditor : Unused, maybe will be used later reg rst_port; // @SuppressThisWarning VEditor : Unused, maybe will be used later reg ghc_ie_r; reg ghc_is_r; Loading @@ -104,16 +146,43 @@ module ahci_ctrl_stat #( reg [31:0] PxIE_r; // some bits will be unused by PxIS_MASK reg [31:0] PxIS_r; // some bits will be unused by PxIS_MASK reg [11:0] PxSSTS_r; reg [31:0] PxSERR_r; // Assuming it is not needed for HBA, just for the software reg [31:0] PxCMD_r; reg pxci0_r; wire [31:0] sirq = {32{sirq_TFE}} & HBA_PORT__PxIS__TFES__MASK | // 'h40000000; {32{sirq_IF }} & HBA_PORT__PxIS__IFS__MASK | // 'h8000000; {32{sirq_INF}} & HBA_PORT__PxIS__INFS__MASK | // 'h4000000; {32{sirq_OF }} & HBA_PORT__PxIS__OFS__MASK | // 'h1000000; {32{sirq_PRC}} & HBA_PORT__PxIS__PRCS__MASK | // 'h400000; {32{sirq_PC}} & HBA_PORT__PxIS__PCS__MASK | // 'h40;; {32{sirq_DP}} & HBA_PORT__PxIS__DPS__MASK | // 'h20; {32{sirq_UF }} & HBA_PORT__PxIS__UFS__MASK | // 'h10; {32{sirq_SDB}} & HBA_PORT__PxIS__SDBS__MASK | // 'h8; {32{sirq_DS }} & HBA_PORT__PxIS__DSS__MASK | // 'h4; {32{sirq_PS }} & HBA_PORT__PxIS__PSS__MASK | // 'h2; {32{sirq_DHR}} & HBA_PORT__PxIS__DHRS__MASK; // 'h1; wire [31:0] serr = {32{sirq_PC}} & HBA_PORT__PxSERR__DIAG__X__MASK | // 'h4000000; {32{sirq_UF }} & HBA_PORT__PxSERR__DIAG__F__MASK | // 'h2000000; {32{serr_DT }} & HBA_PORT__PxSERR__DIAG__T__MASK | // 'h1000000; {32{serr_DS }} & HBA_PORT__PxSERR__DIAG__S__MASK | // 'h800000; {32{serr_DH }} & HBA_PORT__PxSERR__DIAG__H__MASK | // 'h400000; {32{serr_DC }} & HBA_PORT__PxSERR__DIAG__C__MASK | // 'h200000; {32{serr_DB }} & HBA_PORT__PxSERR__DIAG__B__MASK | // 'h80000; {32{serr_DW }} & HBA_PORT__PxSERR__DIAG__W__MASK | // 'h40000; {32{serr_DI }} & HBA_PORT__PxSERR__DIAG__I__MASK | // 'h20000; {32{sirq_PRC}} & HBA_PORT__PxSERR__DIAG__N__MASK | // 'h10000; {32{sirq_IF | sirq_INF }} & HBA_PORT__PxSERR__ERR__E__MASK | // 'h800; {32{serr_EP }} & HBA_PORT__PxSERR__ERR__P__MASK | // 'h400; {32{serr_EC }} & HBA_PORT__PxSERR__ERR__C__MASK | // 'h200; {32{serr_ET }} & HBA_PORT__PxSERR__ERR__T__MASK | // 'h100; {32{serr_EM }} & HBA_PORT__PxSERR__ERR__M__MASK | // 'h2; {32{serr_EI }} & HBA_PORT__PxSERR__ERR__I__MASK; // 'h0; wire [11:8] sssts_ipm = ({4{ssts_ipm_active}} & 4'h1) | ({4{ssts_ipm_part}} & 4'h2) | ({4{ssts_ipm_slumb}} & 4'h6) | Loading @@ -136,6 +205,7 @@ localparam PxIE_MASK = HBA_PORT__PxIE__TFEE__MASK | // 'h40000000; HBA_PORT__PxIE__DSE__MASK | // 'h4; HBA_PORT__PxIE__PSE__MASK | // 'h2; HBA_PORT__PxIE__DHRE__MASK; // 'h1; localparam PxIS_MASK = HBA_PORT__PxIS__TFES__MASK | // 'h40000000; HBA_PORT__PxIS__IFS__MASK | // 'h8000000; HBA_PORT__PxIS__INFS__MASK | // 'h4000000; Loading @@ -147,6 +217,76 @@ localparam PxIS_MASK = HBA_PORT__PxIS__TFES__MASK | // 'h40000000; HBA_PORT__PxIS__PSS__MASK | // 'h2; HBA_PORT__PxIS__DHRS__MASK; // 'h1; localparam PxSERR_MASK = HBA_PORT__PxSERR__DIAG__X__MASK | // 'h4000000; HBA_PORT__PxSERR__DIAG__F__MASK | // 'h2000000; HBA_PORT__PxSERR__DIAG__T__MASK | // 'h1000000; HBA_PORT__PxSERR__DIAG__S__MASK | // 'h800000; HBA_PORT__PxSERR__DIAG__H__MASK | // 'h400000; HBA_PORT__PxSERR__DIAG__C__MASK | // 'h200000; HBA_PORT__PxSERR__DIAG__B__MASK | // 'h80000; HBA_PORT__PxSERR__DIAG__W__MASK | // 'h40000; HBA_PORT__PxSERR__DIAG__I__MASK | // 'h20000; HBA_PORT__PxSERR__DIAG__N__MASK | // 'h10000; HBA_PORT__PxSERR__ERR__E__MASK | // 'h800; HBA_PORT__PxSERR__ERR__P__MASK | // 'h400; HBA_PORT__PxSERR__ERR__C__MASK | // 'h200; HBA_PORT__PxSERR__ERR__T__MASK | // 'h100; HBA_PORT__PxSERR__ERR__M__MASK | // 'h2; HBA_PORT__PxSERR__ERR__I__MASK; // 'h0; localparam PxCMD_DFLT = HBA_PORT__PxCMD__ICC__DFLT | // 'h0; HBA_PORT__PxCMD__ASP__DFLT | // 'h0; HBA_PORT__PxCMD__ALPE__DFLT | // 'h0; HBA_PORT__PxCMD__DLAE__DFLT | // 'h0; HBA_PORT__PxCMD__ATAPI__DFLT | // 'h0; HBA_PORT__PxCMD__APSTE__DFLT | // 'h0; HBA_PORT__PxCMD__FBSCP__DFLT | // 'h0; HBA_PORT__PxCMD__ESP__DFLT | // 'h200000; HBA_PORT__PxCMD__CPD__DFLT | // 'h0; HBA_PORT__PxCMD__MPSP__DFLT | // 'h0; HBA_PORT__PxCMD__HPCP__DFLT | // 'h40000; HBA_PORT__PxCMD__PMA__DFLT | // 'h0; HBA_PORT__PxCMD__CPS__DFLT | // 'h0; HBA_PORT__PxCMD__CR__DFLT | // 'h0; HBA_PORT__PxCMD__FR__DFLT | // 'h0; HBA_PORT__PxCMD__MPSS__DFLT | // 'h0; HBA_PORT__PxCMD__CCS__DFLT | // 'h0; HBA_PORT__PxCMD__FRE__DFLT | // 'h0; HBA_PORT__PxCMD__CLO__DFLT | // 'h0; HBA_PORT__PxCMD__POD__DFLT | // 'h4; HBA_PORT__PxCMD__SUD__DFLT | // 'h2; HBA_PORT__PxCMD__ST__DFLT; // 'h0; localparam PxCMD_MASK = HBA_PORT__PxCMD__ICC__MASK | // 'hf0000000; // HBA_PORT__PxCMD__ASP__MASK | // 'h8000000; // HBA_PORT__PxCMD__ALPE__MASK | // 'h4000000; // HBA_PORT__PxCMD__DLAE__MASK | // 'h2000000; // HBA_PORT__PxCMD__ATAPI__MASK | // 'h1000000; // HBA_PORT__PxCMD__APSTE__MASK | // 'h800000; // HBA_PORT__PxCMD__FBSCP__MASK | // 'h400000; HBA_PORT__PxCMD__ESP__MASK | // 'h200000; // HBA_PORT__PxCMD__CPD__MASK | // 'h100000; // HBA_PORT__PxCMD__MPSP__MASK | // 'h80000; // HBA_PORT__PxCMD__HPCP__MASK | // 'h40000; // HBA_PORT__PxCMD__PMA__MASK | // 'h20000; // HBA_PORT__PxCMD__CPS__MASK | // 'h10000; HBA_PORT__PxCMD__CR__MASK | // 'h8000; HBA_PORT__PxCMD__FR__MASK | // 'h4000; // HBA_PORT__PxCMD__MPSS__MASK | // 'h2000; // HBA_PORT__PxCMD__CCS__MASK | // 'h1f00; HBA_PORT__PxCMD__FRE__MASK | // 'h10; HBA_PORT__PxCMD__CLO__MASK | // 'h8; // HBA_PORT__PxCMD__POD__MASK | // 'h4; // HBA_PORT__PxCMD__SUD__MASK | // 'h2; HBA_PORT__PxCMD__ST__MASK; // 'h1; assign pxci0 = pxci0_r; assign pcmd_cr = PxCMD_r[15]; // command list run - current assign pcmd_clo = PxCMD_r[3]; // causes ahci_fis_receive:clear_bsy_drq, that in turn resets this bit assign pcmd_st = PxCMD_r[0]; // current value always @(posedge mclk) begin if (mrst) irq <= 0; Loading Loading @@ -187,40 +327,74 @@ localparam PxIS_MASK = HBA_PORT__PxIS__TFES__MASK | // 'h40000000; else PxIS_r <= PxIS_MASK & ((swr_HBA_PORT__PxIS ? soft_write_data : PxIS_r) | sirq); end // HBA_PORT__PxIE register always @(posedge mclk) begin if (rst_por) set_ghc_is_r <= 0; // TODO: Not exactly clear - when ghc_is_r should be set after being RWC? After setting some not masked new individual interrupt? else set_ghc_is_r <= |(sirq & PxIE_r); end // HBA_PORT__PxSSTS register - updated from the HOST only always @(posedge mclk) begin if (mrst) PxSSTS_r[11:8] <= 0; else if (ssts_ipm_dnp || ssts_ipm_active || ssts_ipm_part || ssts_ipm_slumb || ssts_ipm_devsleep) PxSSTS_r[11:8] <= sssts_ipm[11:8]; if (mrst) PxSSTS_r[ 7:4] <= 0; else if (ssts_ipm_dnp || ssts_ipm_active || ssts_ipm_part || ssts_ipm_slumb || ssts_ipm_devsleep) PxSSTS_r[ 7:4] <= sssts_spd[ 7:4]; else if (ssts_spd_dnp || ssts_spd_gen1 || ssts_spd_gen2|| ssts_spd_gen3) PxSSTS_r[ 7:4] <= sssts_spd[ 7:4]; if (mrst) PxSSTS_r[ 3:0] <= 0; else if (ssts_ipm_dnp || ssts_ipm_active || ssts_ipm_part || ssts_ipm_slumb || ssts_ipm_devsleep) PxSSTS_r[ 3:0] <= sssts_det[ 3:0]; else if (ssts_det_ndnp || ssts_det_dnp || ssts_det_dp || ssts_det_offline) PxSSTS_r[ 3:0] <= sssts_det[ 3:0]; end // HBA_PORT__PxSCTL register - updated by the software only always @ (posedge mclk) begin if (rst_por) {sctl_ipm, sctl_spd, sctl_det} <= 0; else if (swr_HBA_PORT__PxSCTL) {sctl_ipm, sctl_spd, sctl_det} <= soft_write_data [11:0]; end // HBA_PORT__PxSERR register always @(posedge mclk) begin if (rst_por) PxSERR_r <= 0; else PxSERR_r <= PxSERR_MASK & ((swr_HBA_PORT__PxSERR ? soft_write_data : PxSERR_r) | serr); end // HBA_PORT__PxCI[0] register - cleared by HBA, set by software always @(posedge mclk) begin if (mrst || pxci0_clear) pxci0_r <= 0; else if (swr_HBA_PORT__PxCI) pxci0_r <= soft_write_data[0]; end // HBA_PORT__PxCMD register - different behavious of differtnt fields // use PxCMD_MASK to prevent generation of unneeded register bits always @(posedge mclk) begin if (mrst) PxCMD_r <= PxCMD_DFLT; else PxCMD_r <= (~PxCMD_MASK & PxCMD_DFLT ) | (PxCMD_MASK & ( swr_HBA_PORT__PxCMD? soft_write_data : ( (pcmd_clear_icc ? 0 : (PxCMD_r & HBA_PORT__PxCMD__ICC__MASK)) | (pcmd_esp ? HBA_PORT__PxCMD__ESP__MASK : 0) | (pcmd_cr_reset ? 0 : (HBA_PORT__PxCMD__CR__MASK & (pcmd_cr_set? (~0):(PxCMD_r)))) | (pcmd_fr? HBA_PORT__PxCMD__FR__MASK : 0 ) | (HBA_PORT__PxCMD__FRE__MASK & PxCMD_r) | // no HBA control (pcmd_clear_bsy_drq ? 0 : (PxCMD_r & HBA_PORT__PxCMD__CLO__MASK)) | (pcmd_clear_st ? 0 : (PxCMD_r & HBA_PORT__PxCMD__ST__MASK)) ))); end // Update AXI registers with the current local data always @ (posedge mclk) begin regs_addr <= ({ADDRESS_BITS{update_GHC__IS}} & GHC__IS__IPS__ADDR) | ({ADDRESS_BITS{update_HBA_PORT__PxIS}} & HBA_PORT__PxIS__CPDS__ADDR) | // TODO: add more ... ({ADDRESS_BITS{update_HBA_PORT__PxSSTS}} & HBA_PORT__PxSSTS__SPD__ADDR) ; ({ADDRESS_BITS{update_HBA_PORT__PxIS}} & HBA_PORT__PxIS__CPDS__ADDR) | ({ADDRESS_BITS{update_HBA_PORT__PxSSTS}} & HBA_PORT__PxSSTS__SPD__ADDR) | ({ADDRESS_BITS{update_HBA_PORT__PxSERR}} & HBA_PORT__PxSERR__DIAG__X__ADDR) | ({ADDRESS_BITS{update_HBA_PORT__PxCMD}} & HBA_PORT__PxCMD__ICC__ADDR); regs_din <= ({32{update_GHC__IS}} & {31'b0, ghc_is_r}) | ({32{update_HBA_PORT__PxIS}} & PxIS_r) | // TODO: add more ... ({32{update_HBA_PORT__PxSSTS}} &{20'b0, PxSSTS_r[11:0]}); // | // TODO: add more ... ({32{update_HBA_PORT__PxIS}} & PxIS_r) | ({32{update_HBA_PORT__PxSSTS}} & {20'b0, PxSSTS_r[11:0]}) | ({32{update_HBA_PORT__PxSERR}} & PxSERR_r) | ({32{update_HBA_PORT__PxCMD}} & PxCMD_r); regs_we <= update_GHC__IS || update_HBA_PORT__PxIS || update_HBA_PORT__PxSSTS; regs_we <= update_GHC__IS || update_HBA_PORT__PxIS || update_HBA_PORT__PxSSTS || update_HBA_PORT__PxSERR | update_HBA_PORT__PxCMD; end // /* sirq */ endmodule
ahci/ahci_top.v +73 −0 Original line number Diff line number Diff line Loading @@ -426,6 +426,79 @@ module ahci_top#( ); /* Instance template for module ahci_ctrl_stat */ ahci_ctrl_stat #( .ADDRESS_BITS (ADDRESS_BITS) ) ahci_ctrl_stat_i ( .mrst (), // input .mclk (), // input .was_hba_rst (), // input .was_port_rst (), // input .soft_write_addr (), // input[9:0] .soft_write_data (), // input[31:0] .soft_write_en (), // input .regs_addr (), // output[9:0] reg .regs_we (), // output reg .regs_din (), // output[31:0] reg .update_GHC__IS (), // input .update_HBA_PORT__PxIS (), // input .update_HBA_PORT__PxSSTS (), // input .update_HBA_PORT__PxSERR (), // input .update_HBA_PORT__PxCMD (), // input .pcmd_clear_icc (), // input .pcmd_esp (), // input .pcmd_cr (), // output .pcmd_cr_set (), // input .pcmd_cr_reset (), // input .pcmd_fr (), // input .pcmd_clear_bsy_drq (), // input .pcmd_clo (), // output .pcmd_clear_st (), // input .pcmd_st (), // output .sirq_TFE (), // input .sirq_IF (), // input .sirq_INF (), // input .sirq_OF (), // input .sirq_PRC (), // input .sirq_PC (), // input .sirq_DP (), // input .sirq_UF (), // input .sirq_SDB (), // input .sirq_DS (), // input .sirq_PS (), // input .sirq_DHR (), // input .serr_DT (), // input .serr_DS (), // input .serr_DH (), // input .serr_DC (), // input .serr_DB (), // input .serr_DW (), // input .serr_DI (), // input .serr_EP (), // input .serr_EC (), // input .serr_ET (), // input .serr_EM (), // input .serr_EI (), // input .ssts_ipm_dnp (), // input .ssts_ipm_active (), // input .ssts_ipm_part (), // input .ssts_ipm_slumb (), // input .ssts_ipm_devsleep (), // input .ssts_spd_dnp (), // input .ssts_spd_gen1 (), // input .ssts_spd_gen2 (), // input .ssts_spd_gen3 (), // input .ssts_det_ndnp (), // input .ssts_det_dnp (), // input .ssts_det_dp (), // input .ssts_det_offline (), // input .sctl_ipm (), // output[3:0] reg .sctl_spd (), // output[3:0] reg .sctl_det (), // output[3:0] reg .pxci0_clear (), // input .pxci0 (), // output .irq () // output reg ); ahci_dma ahci_dma_i ( .mrst (mrst), // input Loading