Commit 8db8ea19 authored by Andrey Filippov's avatar Andrey Filippov

Working on AHCI registers

parent 6efdc1f7
......@@ -5,6 +5,11 @@
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.python.pydev.PyDevBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.elphel.vdt.veditor.simulateBuilder</name>
<arguments>
......@@ -41,6 +46,7 @@
</buildSpec>
<natures>
<nature>com.elphel.vdt.veditor.HdlNature</nature>
<nature>org.python.pydev.pythonNature</nature>
</natures>
<linkedResources>
<link>
......
......@@ -100,6 +100,7 @@ axibram_write(
.dev_ready (1'b1),
.bram_wclk (),
.bram_waddr (bram_waddr[15:0]),
.pre_bram_wen (),
.bram_wen (bram_wen),
.bram_wstb (bram_wstb),
.bram_wdata (bram_wdata)
......
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import print_function
from __future__ import division
# Copyright (C) 2015, Elphel.inc.
# Helper module create AHCI registers type/default data
# This program 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.
#
# This program 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/>.
#
__author__ = "Andrey Filippov"
__copyright__ = "Copyright 2015, Elphel, Inc."
__license__ = "GPL"
__version__ = "3.0+"
__maintainer__ = "Andrey Filippov"
__email__ = "andrey@elphel.com"
__status__ = "Development"
import sys
gN = "groupName"
gS = "groupStart"
gE = "groupEnd"
gD = "groupDescription"
gC = "groupContent"
rN = "rangeName" # byte/word/dword
rS = "rangeStart" # in bytes relative to the Group start
rE = "rangeEnd" # in bytes relative to the Group start
rD = "rangeDescription"
rC = "rangeContent"
fN = "fieldName"
fL = "fieldOffsetLow" # if any of fL, fH is absent, it is assumed to be equal to the other, if both - to the full range
fH = "fieldOffsetHigh"
fS = "fieldSize"
fD = "fieldDescription"
fC = "fieldContent"
fT = "fieldType"
RW = "RW"
RO= "RO"
RWC = "RWC"
RW1 = "RW1"
# All unspecified ranges/fields default to fT:RO, fC:0 (readonly, reset value = 0)
VID = 0xfffe # What to use for non-PCI "vendorID"?
DID = 0x0001
SSVID = 0xfffe
SSID = 0x0001
IPIN = 0x01 # TODO: Put a real number for "Interrupt pin"
ILINE = 0x00 # Interrupt line - software is supposed to fill it - maybe here we need to put some predefined value?
HBA_OFFS = 0x0
#HBA_PORT0 = 0x100 Not needed, always HBA_OFFS + 0x100
PCIHEAD = 0x180
PMCAP = 0x1C0
ABAR = 0x80000000 + HBA_OFFS
P0CLB = 0x0 # Port 0 CLB address - define here?
P0FB = 0x0 # Port 0 received FIS address - define here?
src=[{gN:"PCI_Header", gS: PCIHEAD, gE:PCIHEAD+0x3f, gD:" PCI header emulation with no PCI",gC:
[{rN:"ID", rS:0x0, rE:0x3, rD:"Identifiers", rC:
[{fN:"DID", fS:16, fE:31, fT:RO, fC:DID, fD:"Device ID"},
{fN:"VID", fS:0, fE:15, fT:RO, fC:VID, fD:"Vendor ID"}]},
{rN:"CMD", rS:0x04, rE:0x5, rD:"Command Register", rC:
[{fS:11, fE:15, fT:RO, fC:0}, # reserved
{fN:"ID", fS:10, fT:RW, fC:0, fD:"HBA Interrupt Disable"},
{fN:"FBE", fS: 9, fT:RO, fC:0, fD:"Fast Back-to-Back Enable"},
{fN:"SEE", fS: 8, fT:RO, fC:0, fD:"SERR Enable"},
{fN:"WCC", fS: 7, fT:RO, fC:0, fD:"Reserved"},
{fN:"PEE", fS: 6, fT:RO, fC:0, fD:"Parity Error Response Enable"},
{fN:"VGA", fS: 5, fT:RO, fC:0, fD:"Reserved"},
{fN:"MWIE",fS: 4, fT:RO, fC:0, fD:"Reserved"},
{fN:"SCE", fS: 3, fT:RO, fC:0, fD:"Reserved"},
{fN:"BME", fS: 2, fT:RW, fC:0, fD:"Bus Master Enable (0 - stops any DMA)"},
{fN:"MSE", fS: 1, fT:RW, fC:0, fD:"Memory Space enable (here - always?)"},
{fN:"IOSE",fS: 0, fT:RO, fC:0, fD:"Enable IO space access (only for legacy IDE)"}]},
{rN:"STS", rS:0x06, rE:0x7, rD:"Device Status", rC:
[{fN:"DPE", fS:15, fT:RWC, fC:0, fD:"Detected Parity Error"},
{fN:"SSE", fS:14, fT:RWC, fC:0, fD:"Signaled System Error (HBA SERR)"},
{fN:"RMA", fS:13, fT:RWC, fC:0, fD:"Received Master Abort"},
{fN:"RTA", fS:12, fT:RWC, fC:0, fD:"Received Target Abort"},
{fN:"STA", fS:11, fT:RWC, fC:0, fD:"Signaled Target Abort"},
{fN:"DEVT",fS: 9, fE:10, fT:RO, fC:0, fD:"PCI DEVSEL Timing"},
{fN:"DPD", fS: 8, fT:RWC, fC:0, fD:"Master Data Parity Error Detected"},
{fN:"FBC", fS: 7, fT:RO, fC:0, fD:"Fast Back-To-Back Capable"},
{ fS: 6, fT:RO, fC:0, fD:"Reserved"},
{fN:"C66", fS: 5, fT:RO, fC:0, fD:"66 MHz Capable"},
{fN:"CL", fS: 4, fT:RO, fC:1, fD:"Capabilities List (PCI power management mandatory)"},
{fN:"IS", fS: 3, fT:RO, fC:0, fD:"Interrupt Status (1 - asserted)"},
{ fS: 0, fE:2, fT:RO, fC:0, fD:"Reserved"}]},
{rN:"RID", rS:0x08, rD:"HBA Revision ID", rC:
[{fN:"RID", fT:RO, fC:1, fD:"HBA Revision ID"}]},
{rN:"CC", rS:0x09, rE:0x0b, rD:"Class Code", rC:
[{fN:"BCC", fS:16, fE:23, fT:RO, fC:1, fD:"Base Class Code: 1 - Mass Storage Device"},
{fN:"SCC", fS: 8, fE:15, fT:RO, fC:6, fD:"Sub Class Code: 0x06 - SATA Device"},
{fN:"PI", fS: 8, fE:15, fT:RO, fC:1, fD:"Programming Interface: 1 - AHCI HBA major rev 1"}]},
{rN:"CLS", rS:0x0c, rD:"Cache Line Size", rC:
[{fN:"CLS", fT:RW, fC:0, fD:"Cache Line Size"}]},
{rN:"MLT", rS:0x0d, rD:"Master Latency Timer", rC:
[{fN:"MLT", fT:RW, fC:0, fD:"Master Latency Timer"}]},
{rN:"HTYPE", rS:0x0d, rD:"Header Type", rC:
[{fN:"MFDT",fS:7, fT:RO, fC:0, fD:"Multi-Function Device"},
{fN:"HL", fS: 0, fE:6, fT:RO, fC:0, fD:"Header Layout 0 - HBA uses a target device layout"}]},
#Offsets 0x10..0x23 - other BARs (optional)
{rN:"ABAR", rS:0x24, rE:0x27, rD:"AHCI Base Address", rC:
[{fN:"BA", fS: 4, fE:31, fT:RO, fC:(ABAR >> 4), fD:"AHCI Base Address high bits, normally RW, but here RO to get to MAXIGP1 space"},
{fN:"PF", fS: 3, fT:RO, fC:0, fD:"Prefetchable (this is not)"},
{fN:"TP", fS: 1, fE:2, fT:RO, fC:0, fD:"Type (0 - any 32-bit address, here it is hard-mapped"},
{fN:"RTE", fS: 0, fT:RO, fC:0, fD:"Resource Type Indicator: 0 - memory address"}]},
# 0x28.0x2b skipped
{rN:"SS", rS:0x2c, rE:0x2f, rD:"Sub System identifiers", rC:
[{fN:"SSID", fS:16, fE:31, fT:RO, fC:SSID, fD:"SubSystem ID"},
{fN:"SSVID", fS:0, fE:15, fT:RO, fC:SVID, fD:"SubSystem Vendor ID"}]},
{rN:"EROM", rS:0x30, rE:0x33, rD:"Extension ROM (optional)", rC:
[{fN:"RBA", fT:RO, fC:0, fD:"ROM Base Address"}]},
{rN:"CAP", rS:0x34, rD:"Capabilities Pointer", rC:
[{fN:"CAP", fT:RO, fC:(PMCAP-PCIHEAD), fD:"Capabilities pointer"}]},
#0x35-0x3b are reserved
{rN:"INTR", rS:0x3c, rE:0x3d, rD:"Interrupt Information", rC:
[{fN:"IPIN", fS: 8, fE:15, fT:RO, fC:IPIN, fD:"Interrupt pin"},
{fN:"ILINE", fS: 0, fE: 7, fT:RW, fC:ILINE,fD:"Interrupt Line"}]},
{rN:"MGNT", rS:0x3e, rD:"Minimal Grant (optional)", rC:
[{fN:"MGNT", fT:R0, fC:0, fD:"Minimal Grant"}]},
{rN:"MLAT", rS:0x3f, rD:"Maximal Latency (optional)", rC:
[{fN:"MLAT", fT:R0, fC:0, fD:"Maximal Latency"}]}
]}, # End of "PCI_Header" group
{gN:"PMCAP", gS: PMCAP, gE:PMCAP+0x7, gD:"Power Management Capability",gC:
[{rN:"PID", rS:0x0, rE:0x1, rD:"PCI Power Management Capability ID", rC:
[{fN:"NEXT", fS: 8, fE:15, fT:RO, fC:0, fD:"Next Capability pointer"},
{fN:"CID", fS: 0, fE: 7, fT:RO, fC:1, fD:"This is PCI Power Management Capability"}]},
{rN:"PC", rS:0x2, rE:0x3, rD:"Power Management Capabilities", rC:
[{fN:"PSUP", fS:11, fE:15, fT:RO, fC:8, fD:"PME_SUPPORT bits:'b01000"},
{fN:"D2S", fS:10, fT:RO, fC:0, fD:"D2 Support - no"},
{fN:"D1S", fS: 9, fT:RO, fC:0, fD:"D1 Support - no"},
{fN:"AUXC", fS: 6, fE: 8, fT:RO, fC:0, fD:"Maximal D3cold current"},
{fN:"DSI", fS: 5, fT:RO, fC:0, fD:"Device-specific initialization required"}, #Use it?
{ fS: 4, fT:RO, fC:0, fD:"Reserved"},
{fN:"PMEC", fS: 3, fT:RO, fC:0, fD:"PCI clock required to generate PME"},
{fN:"VS", fS: 0, fE: 2, fT:RO, fC:0, fD:"Revision of Power Management Specification support version"}]},
{rN:"PMCS", rS:0x4, rE:0x5, rD:"Power Management Control and Status", rC:
[{fN:"PMES", fS:15, fT:RWC,fC:0, fD:"PME Status, set by hardware when HBA generates PME"},
{ fS: 9, fE:14, fT:RO, fC:0, fD:"Reserved: AHCI HBA Does not implement data register"},
{fN:"PMEE", fS: 8, fT:RW, fC:0, fD:"PME Enable"},
{ fS: 2, fE: 7, fT:RO, fC:0, fD:"Reserved"},
{fN:"PS", fS: 0, fE: 1, fT:RW, fC:0, fD:"Power State"}]},
]},
{gN:"GHC", gS: HBA_OFFS, gE:HBA_OFFS + 0x2b, gD:"HBA Generic Host Control",gC:
[{rN:"CAP", rS:0x0, rE:0x03, rD:"HBA Capabilities", rC:
[{fN:"S64A", fS:31, fT:RO, fC:0, fD:"Supports 64-bit Addressing - no"},
{fN:"SNCQ", fS:30, fT:RO, fC:0, fD:"Supports Native Command Queuing - no"},
{fN:"SSNTF", fS:29, fT:RO, fC:0, fD:"Supports SNotification Register - no"},
{fN:"SMPS", fS:28, fT:RO, fC:0, fD:"Supports Mechanical Presence Switch - no"},
{fN:"SSS", fS:27, fT:RO, fC:0, fD:"Supports Staggered Spin-up - no"},
{fN:"SALP", fS:26, fT:RO, fC:0, fD:"Supports Aggressive Link Power Management - no"},
{fN:"SAL", fS:25, fT:RO, fC:0, fD:"Supports Activity LED - no"},
{fN:"SCLO", fS:24, fT:RO, fC:0, fD:"Supports Command List Override - no (not capable of clearing BSY and DRQ bits, needs soft reset"},
{fN:"ISS", fS:20, fe:23, fT:RO, fC:2, fD:"Interface Maximal speed: 2 - Gen2, 3 - Gen3"},
{ fS:19, fT:RO, fC:0, fD:"Reserved"},
{fN:"SAM", fS:18, fT:RO, fC:1, fD:"AHCI only (0 - legacy too)"},
{fN:"SPM", fS:17, fT:RO, fC:0, fD:"Supports Port Multiplier - no"},
{fN:"FBSS", fS:16, fT:RO, fC:0, fD:"Supports FIS-based switching of the Port Multiplier - no"},
{fN:"PMD", fS:15, fT:RO, fC:0, fD:"PIO Multiple DRQ block - no"},
{fN:"SSC", fS:14, fT:RO, fC:0, fD:"Slumber State Capable - no"},
{fN:"PSC", fS:13, fT:RO, fC:0, fD:"Partial State Capable - no"},
{fN:"NSC", fS: 8, fe:12, fT:RO, fC:0, fD:"Number of Command Slots, 0-based (0 means 1?)"},
{fN:"CCCS", fS: 7, fT:RO, fC:0, fD:"Command Completion Coalescing - no"},
{fN:"EMS", fS: 6, fT:RO, fC:0, fD:"Enclosure Management - no"},
{fN:"SXS", fS: 5, fT:RO, fC:1, fD:"External SATA connector - yes"},
{fN:"NP", fS: 0, fe: 4, fT:RO, fC:0, fD:"Number of Ports, 0-based (0 means 1?)"}]},
{rN:"GHC", rS:0x4, rE:0x07, rD:"Global HBA Control", rC:
[{fN:"AE", fS:31, fT:RO, fC:1, fD:"AHCI enable (0 - legacy)"},
{ fS: 3, fe:30, fT:RO, fC:0, fD:"Reserved"},
{fN:"MRSM", fS: 2, fT:RO, fC:0, fD:"MSI Revert to Single Message"},
{fN:"IE", fS: 1, fT:RW, fC:0, fD:"Interrupt Enable (all ports)"},
{fN:"HR", fS: 0, fT:RW1,fC:0, fD:"HBA reset (COMINIT, ...). Set by software, cleared by hardware, section 10.4.3"}]},
{rN:"IS", rS:0x08, rE:0x0b, rD:"Interrupt Status Register", rC:
[{fN:"IPS", fT:RWC,fC:0, fD:"Interrupt Pending Status (per port)"}]},
{rN:"PI", rS:0x0c, rE:0x0f, rD:"Interrupt Status Register", rC:
[{fN:"PI", fT:RO, fC:1, fD:"Ports Implemented"}]},
{rN:"VS", rS:0x10, rE:0x13, rD:"AHCI Verion", rC:
[{fN:"MJR", fS:16, fE:31, fT:RO, fC:0x0001, fD:"AHCI Major Verion 1."},
{fN:"MNR", fS: 0, fE:15, fT:RO, fC:0x0301, fD:"AHCI Minor Verion 3.1"}]},
{rN:"CCC_CTL", rS:0x14, rE:0x17, rD:"Command Completion Coalescing Control", rC:
[{ fT:RO, fC:0, fD:"Not Implemented"}]},
{rN:"CCC_PORTS", rS:0x18, rE:0x1b, rD:"Command Completion Coalescing Ports", rC:
[{ fT:RO, fC:0, fD:"Not Implemented"}]},
{rN:"EM_LOC", rS:0x1c, rE:0x1f, rD:"Enclosure Management Location", rC:
[{ fT:RO, fC:0, fD:"Not Implemented"}]},
{rN:"EM_CTL", rS:0x20, rE:0x23, rD:"Enclosure Management Control", rC:
[{ fT:RO, fC:0, fD:"Not Implemented"}]},
{rN:"CAP2", rS:0x24, rE:0x27, rD:"HBA Capabilities Extended", rC:
[{ fs: 6, fE:31, fT:RO, fC:0, fD:"Reserved"},
{fN:"DESO", fS: 5, fT:RO, fC:0, fD:"DevSleep Entrance from Slumber Only"},
{fN:"SADM", fS: 4, fT:RO, fC:0, fD:"Supports Aggressive Device Sleep Management"},
{fN:"SDS", fS: 3, fT:RO, fC:0, fD:"Supports Device Sleep"},
{fN:"APST", fS: 2, fT:RO, fC:0, fD:"Automatic Partial to Slumber Transitions"},
{fN:"NVMP", fS: 1, fT:RO, fC:0, fD:"NVMHCI Present (section 10.15)"},
{fN:"BOH", fS: 0, fT:RO, fC:0, fD:"BIOS/OS Handoff - not supported"}]},
{rN:"BOHC", rS:0x28, rE:0x2b, rD:"BIOS/OS COntrol and status", rC:
[{ fT:RO, fC:0, fD:"Not Implemented"}]},
]},
{gN:"HBA_PORT", gS: HBA_OFFS + 0x100, gE:HBA_OFFS + 0x17f, gD:"HBA Port registers",gC:
[{rN:"PxCLB", rS:0x0, rE:0x03, rD:"Port x Command List Base Address", rC:
[{fN:"CLB", fS:10, fE:31, fT:RW, fC:P0CLB>>10, fD:"Command List Base Address (1KB aligned)"},
{ fS: 0, fe: 9, fT:RO, fC:0, fD:"Reserved"}]},
{rN:"PxCLBU", rS:0x04, rE:0x07, rD:"Port x CLB address, upper 32 bits of 64", rC:
[{ fT:RO, fC:0, fD:"Not Implemented"}]},
{rN:"PxFB", rS:0x8, rE:0x0b, rD:"FIS Base Address", rC:
[{fN:"CLB", fS: 8, fE:31, fT:RW, fC:P0FB>> 8, fD:"Command List Base Address (1KB aligned)"},
{ fS: 0, fe: 7, fT:RO, fC:0, fD:"Reserved"}]},
{rN:"PxFBU", rS:0x0c, rE:0x0f, rD:"FIS address, upper 32 bits of 64", rC:
[{ fT:RO, fC:0, fD:"Not Implemented"}]},
{rN:"PxIS", rS:0x10, rE:0x13, rD:"Port x Interrupt Status", rC:
[{fN:"CPDS", fS:31, fT:RWC,fC:0, fD:"Cold Port Detect Status"},
{fN:"TFES", fS:30, fT:RWC,fC:0, fD:"Task File Error Status"},
{fN:"HBFS", fS:29, fT:RWC,fC:0, fD:"Host Bus (PCI) Fatal error"},
{fN:"HBDS", fS:28, fT:RWC,fC:0, fD:"ECC error R/W system memory"},
{fN:"IFS", fS:27, fT:RWC,fC:0, fD:"Interface Fatal Error Status (sect. 6.1.2)"},
{fN:"INFS", fS:26, fT:RWC,fC:0, fD:"Interface Non-Fatal Error Status (sect. 6.1.2)"},
{ fS:25, fT:RO, fC:0, fD:"Reserved"},
{fN:"OFS", fS:24, fT:RWC,fC:0, fD:"Overflow Status"},
{fN:"IPMS", fS:23, fT:RWC,fC:0, fD:"Incorrect Port Multiplier Status"},
{fN:"PRCS", fS:22, fT:RO, fC:0, fD:"PhyRdy changed Status"}, #Indirect clear
{ fS: 8, fE:21, fT:RO, fC:0, fD:"Reserved"},
{fN:"DMPS", fS: 7, fT:RO, fC:0, fD:"Device Mechanical Presence Status"}, #Indirect clear
{fN:"PCS", fS: 6, fT:RO, fC:0, fD:"Port Connect Change Status"}, #Indirect clear
{fN:"DPS", fS: 5, fT:RWC,fC:0, fD:"Descriptor Processed"},
{fN:"UFS", fS: 4, fT:RO, fC:0, fD:"Unknown FIS"}, #Indirect clear
{fN:"SDBS", fS: 3, fT:RWC,fC:0, fD:"Set Device Bits Interrupt - Set Device bits FIS with 'I' bit set"},
{fN:"DSS", fS: 2, fT:RWC,fC:0, fD:"DMA Setup FIS Interrupt - DMA Setup FIS received with 'I' bit set"},
{fN:"PSS", fS: 1, fT:RWC,fC:0, fD:"PIO Setup FIS Interrupt - PIO Setup FIS received with 'I' bit set"},
{fN:"DHRS", fS: 0, fT:RWC,fC:0, fD:"D2H Register FIS Interrupt - D2H Register FIS received with 'I' bit set"}]},
]},
]
"""
{rN:"??", rS:0x06, rE:0x7, rD:"????", rC:
[]},
VID = 0xfffe # What to use for non-PCI "vendorID"?
DID = 0x0001
SSVID = 0xfffe
SSID = 0x0001
IPIN = 0x01 # TODO: Put a real number for "Interrupt pin"
ILINE = 0x00 # Interrupt line - software is supposed to fill it - maybe here we need to put some predefined value?
HBA_OFFS = 0x0
#HBA_PORT0 = 0x100 Not needed, always HBA_OFFS + 0x100
PCIHEAD = 0x180
PMCAP = 0x1C0
ABAR = 0x80000000 + HBA_OFFS
P0CLB = 0x0 # Port 0 CLB address - define here?
"""
\ No newline at end of file
/*******************************************************************************
* Module: axi_ahci_regs
* Date:2015-12-29
* Author: Andrey Filippov
* Description: Registers for single-port AHCI over AXI implementation
* Combination of PCI Headers, PCI power management, and HBA memory
* 128 DWORD registers
* Registers, with bits being RO, RW, RWC, RW1
*
* Copyright (c) 2015 Elphel, Inc .
* axi_ahci_regs.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.
*
* axi_ahci_regs.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 axi_ahci_regs#(
parameter ADDRESS_BITS = 8 // number of memory address bits
)(
input aclk, // clock - should be buffered
input arst, // @aclk sync reset, active high
// AXI Write Address
input [31:0] awaddr, // AWADDR[31:0], input
input awvalid, // AWVALID, input
output awready, // AWREADY, output
input [11:0] awid, // AWID[11:0], input
input [ 3:0] awlen, // AWLEN[3:0], input
input [ 1:0] awsize, // AWSIZE[1:0], input
input [ 1:0] awburst, // AWBURST[1:0], input
// AXI PS Master GP0: Write Data
input [31:0] wdata, // WDATA[31:0], input
input wvalid, // WVALID, input
output wready, // WREADY, output
input [11:0] wid, // WID[11:0], input
input wlast, // WLAST, input
input [ 3:0] wstb, // WSTRB[3:0], input
// AXI PS Master GP0: Write Responce
output bvalid, // BVALID, output
input bready, // BREADY, input
output [11:0] bid, // BID[11:0], output
output [ 1:0] bresp, // BRESP[1:0], output
// AXI Read Address
input [31:0] araddr, // ARADDR[31:0], input
input arvalid, // ARVALID, input
output arready, // ARREADY, output
input [11:0] arid, // ARID[11:0], input
input [ 3:0] arlen, // ARLEN[3:0], input
input [ 1:0] arsize, // ARSIZE[1:0], input
input [ 1:0] arburst, // ARBURST[1:0], input
// AXI Read Data
output [31:0] rdata, // RDATA[31:0], output
output rvalid, // RVALID, output
input rready, // RREADY, input
output [11:0] rid, // RID[11:0], output
output rlast, // RLAST, output
output [ 1:0] rresp, // RRESP
// HBA interface
// 1. Notification of data written @ hba_clk
output [ADDRESS_BITS-1:0] soft_write_addr, // register address written by software
output [31:0] soft_write_data, // register data written (after applying wstb and type (RO, RW, RWC, RW1)
output soft_write_en, // write enable for data write
output soft_arst, // reset SATA PHY not relying on SATA clock
// TODO: Decode from {bram_addr, ahci_regs_di}, bram_wen_d
// 2. HBA R/W registers, use hba clock
input hba_clk,
input hba_rst,
input [ADDRESS_BITS-1:0] hba_addr,
input hba_we,
// input [3:0] hba_wstb, Needed?
input [1:0] hba_re, // [0] - re, [1] - regen
input [31:0] hba_din,
output [31:0] hba_dout
);
wire [ADDRESS_BITS-1:0] bram_waddr;
wire [ADDRESS_BITS-1:0] pre_awaddr;
wire [ADDRESS_BITS-1:0] bram_raddr;
wire [31:0] bram_rdata;
wire pre_bram_wen; // one cycle ahead of bram_wen, nut not masked by dev_ready
wire bram_wen;
wire [ 3:0] bram_wstb;
wire [31:0] bram_wdata;
wire [ADDRESS_BITS-1:0] bram_addr;
wire [1:0] bram_ren;
reg write_busy_r;
wire write_start_burst;
// wire nowrite; // delay write in read-modify-write register accesses
wire write_busy_w = write_busy_r || write_start_burst;
reg [31:0] bram_wdata_r;
reg [31:0] bram_rdata_r;
reg bram_wen_d;
wire [63:0] regbit_type;
wire [31:0] ahci_regs_di;
wire [31:0] wmask = {{8{bram_wstb[3]}},{8{bram_wstb[2]}},{8{bram_wstb[1]}},{8{bram_wstb[0]}}};
assign bram_addr = bram_ren[0] ? bram_raddr : (bram_wen ? bram_waddr : pre_awaddr);
always @(posedge aclk) begin
if (arst) write_busy_r <= 0;
else if (write_start_burst) write_busy_r <= 1;
else if (!pre_bram_wen) write_busy_r <= 0;
if (bram_wen) bram_wdata_r <= bram_wdata;
if (bram_ren[1]) bram_rdata_r <= bram_rdata;
bram_wen_d <= bram_wen;
end
generate
genvar i;
for (i=0; i < 32; i=i+1) begin: bit_type_block
assign ahci_regs_di[i] = (regbit_type[2*i+1] && wmask[i])?
((regbit_type[2*i] && wmask[i])?
(bram_rdata[i] || bram_wdata_r[i]): // 3: RW1
(bram_rdata[i] && !bram_wdata_r[i])): // 2: RWC
((regbit_type[2*i] && wmask[i])?
(bram_wdata_r[i]): // 1: RW write new data
(bram_rdata[i])); // 0: R0 (keep old data)
end
endgenerate
axibram_write #(
.ADDRESS_BITS(ADDRESS_BITS)
) axibram_write_i (
.aclk (aclk), // input
.arst (arst), // input
.awaddr (awaddr), // input[31:0]
.awvalid (awvalid), // input
.awready (awready), // output
.awid (awid), // input[11:0]
.awlen (awlen), // input[3:0]
.awsize (awsize), // input[1:0]
.awburst (awburst), // input[1:0]
.wdata (wdata), // input[31:0]
.wvalid (wvalid), // input
.wready (wready), // output
.wid (wid), // input[11:0]
.wlast (wlast), // input
.wstb (wstb), // input[3:0]
.bvalid (bvalid), // output
.bready (bready), // input
.bid (bid), // output[11:0]
.bresp (bresp), // output[1:0]
.pre_awaddr (pre_awaddr), // output[9:0]
.start_burst (write_start_burst), // output
// .dev_ready (!nowrite && !bram_ren[0]), // input
.dev_ready (!bram_wen), // input There will be no 2 bram_wen in a row
.bram_wclk (), // output
.bram_waddr (bram_waddr), // output[9:0]
.pre_bram_wen(pre_bram_wen), // output
.bram_wen (bram_wen), // output
.bram_wstb (bram_wstb), // output[3:0]
.bram_wdata (bram_wdata) // output[31:0]
);
axibram_read #(
.ADDRESS_BITS(ADDRESS_BITS)
) axibram_read_i (
.aclk (aclk), // input
.arst (arst), // input
.araddr (araddr), // input[31:0]
.arvalid (arvalid), // input
.arready (arready), // output
.arid (arid), // input[11:0]
.arlen (arlen), // input[3:0]
.arsize (arsize), // input[1:0]
.arburst (arburst), // input[1:0]
.rdata (rdata), // output[31:0]
.rvalid (rvalid), // output reg
.rready (rready), // input
.rid (rid), // output[11:0] reg
.rlast (rlast), // output reg
.rresp (rresp), // output[1:0]
.pre_araddr (), // output[9:0]
.start_burst (), // output
.dev_ready (!write_busy_w), // input
.bram_rclk (), // output
.bram_raddr (bram_raddr), // output[9:0]
.bram_ren (bram_ren[0]), // output
.bram_regen (bram_ren[1]), // output
.bram_rdata (bram_rdata_r) // input[31:0]
);
wire [ 9:0] hba_addr_ext = (ADDRESS_BITS == 10)? hba_addr: {{(10-ADDRESS_BITS){1'b0}}, hba_addr} ;
wire [ 9:0] bram_addr_ext = (ADDRESS_BITS == 10)? bram_addr: {{(10-ADDRESS_BITS){1'b0}}, bram_addr} ;
wire [ 8:0] brom_addr_ext = (ADDRESS_BITS == 9)? bram_addr: {{(9-ADDRESS_BITS){1'b0}}, bram_addr} ;
ramt_var_w_var_r #(
.REGISTERS_A (0),
.REGISTERS_B (1),
.LOG2WIDTH_A (5),
.LOG2WIDTH_B (5),
.WRITE_MODE_A("NO_CHANGE"),
.WRITE_MODE_B("NO_CHANGE")
// TODO: include here init (default values)
) ahci_regs_i (
.clk_a (aclk), // input
.addr_a (bram_addr_ext), // input[9:0]
.en_a (bram_ren[0] || write_busy_w), // input
.regen_a (1'b0), // input
// .we_a (write_busy_r && !nowrite), // input
.we_a (bram_wen_d), // input
//
.data_out_a (bram_rdata), // output[31:0]
.data_in_a (ahci_regs_di), // input[31:0]
.clk_b (hba_clk), // input
.addr_b (hba_addr_ext), // input[9:0]
.en_b (hba_we || hba_re[0]), // input
.regen_b (hba_re[1]), // input
.we_b (hba_we), // input
.data_out_b (hba_dout), // output[31:0]
.data_in_b (hba_din) // input[31:0]
);
ram_var_w_var_r #(
.REGISTERS (0),
.LOG2WIDTH_WR (6),
.LOG2WIDTH_RD (6),
.DUMMY(0)
// TODO: include here init (register bit types (RO, RW, RWC, RW1)
) ahci_regs_type_i (
.rclk (aclk), // input
.raddr (brom_addr_ext), // input[8:0]
.ren (bram_wen), // input
.regen (1'b0), // input
.data_out (regbit_type), // output[63:0]
.wclk (1'b0), // input
.waddr (9'b0), // input[8:0]
.we (1'b0), // input
.web (8'b0), // input[7:0]
.data_in (64'b0) // input[63:0]
);
fifo_cross_clocks #(
.DATA_WIDTH(ADDRESS_BITS+32),
.DATA_DEPTH(4)
) ahci_regs_set_i (
.rst (1'b0), // input
.rrst (hba_rst), // input
.wrst (arst), // input
.rclk (hba_clk), // input
.wclk (aclk), // input
.we (bram_wen_d), // input
.re (soft_write_en), // input
.data_in ({bram_addr, ahci_regs_di}), // input[15:0]
.data_out ({soft_write_addr,soft_write_data}), // output[15:0]
.nempty (soft_write_en), // output
.half_empty () // output
);
endmodule
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment