Commit 6fdd001b authored by Andrey Filippov's avatar Andrey Filippov

Created Python script (with AHCI documentation) that generates BRAM...

Created Python script (with AHCI documentation) that generates BRAM initializaion for AHCI memory registers
parent 8db8ea19
...@@ -39,6 +39,7 @@ fN = "fieldName" ...@@ -39,6 +39,7 @@ 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 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" fH = "fieldOffsetHigh"
fS = "fieldSize" fS = "fieldSize"
fE = "fieldEnd"
fD = "fieldDescription" fD = "fieldDescription"
fC = "fieldContent" fC = "fieldContent"
fT = "fieldType" fT = "fieldType"
...@@ -54,12 +55,26 @@ SSID = 0x0001 ...@@ -54,12 +55,26 @@ SSID = 0x0001
IPIN = 0x01 # TODO: Put a real number for "Interrupt pin" 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? ILINE = 0x00 # Interrupt line - software is supposed to fill it - maybe here we need to put some predefined value?
HBA_OFFS = 0x0 HBA_OFFS = 0x0
CLB_OFFS = 0x800 # In the second half of the register space (0x800..0xbff - 1KB)
FB_OFFS = 0xc00 # Needs 0x100 bytes
#HBA_PORT0 = 0x100 Not needed, always HBA_OFFS + 0x100 #HBA_PORT0 = 0x100 Not needed, always HBA_OFFS + 0x100
PCIHEAD = 0x180 PCIHEAD = 0x180
PMCAP = 0x1C0 PMCAP = 0x1C0
ABAR = 0x80000000 + HBA_OFFS AXI_BASEADDR = 0x80000000
P0CLB = 0x0 # Port 0 CLB address - define here?
P0FB = 0x0 # Port 0 received FIS address - define here? reg_defaults_path= "../includes/ahci_defaults.vh"
reg_types_path= "../includes/ahci_types.vh"
ABAR = AXI_BASEADDR + HBA_OFFS
# Second half of the 4KB register memory does not have RO/RW/RWC/RW1 capability (just RW), but has a single-cycle write access
#Keeping CLB and received FIS reduces number of required DMA transfer types - just reading PRDs and Read/Write DMA data
P0CLB = AXI_BASEADDR + CLB_OFFS # Port 0 CLB address - keep in HBA internal memory
P0FB = AXI_BASEADDR + FB_OFFS # Port 0 received FIS address - keep in HBA internal memory
#reg_defaults = [0]*4096 # array of bytes, default value = 0
#bit_types = [0]*2048 # array of words, default value = 0
src=[{gN:"PCI_Header", gS: PCIHEAD, gE:PCIHEAD+0x3f, gD:" PCI header emulation with no PCI",gC: 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: [{rN:"ID", rS:0x0, rE:0x3, rD:"Identifiers", rC:
...@@ -114,7 +129,7 @@ src=[{gN:"PCI_Header", gS: PCIHEAD, gE:PCIHEAD+0x3f, gD:" PCI header emulation w ...@@ -114,7 +129,7 @@ src=[{gN:"PCI_Header", gS: PCIHEAD, gE:PCIHEAD+0x3f, gD:" PCI header emulation w
# 0x28.0x2b skipped # 0x28.0x2b skipped
{rN:"SS", rS:0x2c, rE:0x2f, rD:"Sub System identifiers", rC: {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:"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"}]}, {fN:"SSVID", fS:0, fE:15, fT:RO, fC:SSVID,fD:"SubSystem Vendor ID"}]},
{rN:"EROM", rS:0x30, rE:0x33, rD:"Extension ROM (optional)", rC: {rN:"EROM", rS:0x30, rE:0x33, rD:"Extension ROM (optional)", rC:
[{fN:"RBA", fT:RO, fC:0, fD:"ROM Base Address"}]}, [{fN:"RBA", fT:RO, fC:0, fD:"ROM Base Address"}]},
{rN:"CAP", rS:0x34, rD:"Capabilities Pointer", rC: {rN:"CAP", rS:0x34, rD:"Capabilities Pointer", rC:
...@@ -124,9 +139,9 @@ src=[{gN:"PCI_Header", gS: PCIHEAD, gE:PCIHEAD+0x3f, gD:" PCI header emulation w ...@@ -124,9 +139,9 @@ src=[{gN:"PCI_Header", gS: PCIHEAD, gE:PCIHEAD+0x3f, gD:" PCI header emulation w
[{fN:"IPIN", fS: 8, fE:15, fT:RO, fC:IPIN, fD:"Interrupt pin"}, [{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"}]}, {fN:"ILINE", fS: 0, fE: 7, fT:RW, fC:ILINE,fD:"Interrupt Line"}]},
{rN:"MGNT", rS:0x3e, rD:"Minimal Grant (optional)", rC: {rN:"MGNT", rS:0x3e, rD:"Minimal Grant (optional)", rC:
[{fN:"MGNT", fT:R0, fC:0, fD:"Minimal Grant"}]}, [{fN:"MGNT", fT:RO, fC:0, fD:"Minimal Grant"}]},
{rN:"MLAT", rS:0x3f, rD:"Maximal Latency (optional)", rC: {rN:"MLAT", rS:0x3f, rD:"Maximal Latency (optional)", rC:
[{fN:"MLAT", fT:R0, fC:0, fD:"Maximal Latency"}]} [{fN:"MLAT", fT:RO, fC:0, fD:"Maximal Latency"}]}
]}, # End of "PCI_Header" group ]}, # End of "PCI_Header" group
{gN:"PMCAP", gS: PMCAP, gE:PMCAP+0x7, gD:"Power Management Capability",gC: {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: [{rN:"PID", rS:0x0, rE:0x1, rD:"PCI Power Management Capability ID", rC:
...@@ -159,7 +174,7 @@ src=[{gN:"PCI_Header", gS: PCIHEAD, gE:PCIHEAD+0x3f, gD:" PCI header emulation w ...@@ -159,7 +174,7 @@ src=[{gN:"PCI_Header", gS: PCIHEAD, gE:PCIHEAD+0x3f, gD:" PCI header emulation w
{fN:"SALP", fS:26, fT:RO, fC:0, fD:"Supports Aggressive Link Power Management - 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:"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:"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"}, {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"}, { fS:19, fT:RO, fC:0, fD:"Reserved"},
{fN:"SAM", fS:18, fT:RO, fC:1, fD:"AHCI only (0 - legacy too)"}, {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:"SPM", fS:17, fT:RO, fC:0, fD:"Supports Port Multiplier - no"},
...@@ -167,14 +182,14 @@ src=[{gN:"PCI_Header", gS: PCIHEAD, gE:PCIHEAD+0x3f, gD:" PCI header emulation w ...@@ -167,14 +182,14 @@ src=[{gN:"PCI_Header", gS: PCIHEAD, gE:PCIHEAD+0x3f, gD:" PCI header emulation w
{fN:"PMD", fS:15, fT:RO, fC:0, fD:"PIO Multiple DRQ block - 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:"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:"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:"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:"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:"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:"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?)"}]}, {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: {rN:"GHC", rS:0x4, rE:0x07, rD:"Global HBA Control", rC:
[{fN:"AE", fS:31, fT:RO, fC:1, fD:"AHCI enable (0 - legacy)"}, [{fN:"AE", fS:31, fT:RO, fC:1, fD:"AHCI enable (0 - legacy)"},
{ fS: 3, fe:30, fT:RO, fC:0, fD:"Reserved"}, { 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:"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:"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"}]}, {fN:"HR", fS: 0, fT:RW1,fC:0, fD:"HBA reset (COMINIT, ...). Set by software, cleared by hardware, section 10.4.3"}]},
...@@ -195,7 +210,7 @@ src=[{gN:"PCI_Header", gS: PCIHEAD, gE:PCIHEAD+0x3f, gD:" PCI header emulation w ...@@ -195,7 +210,7 @@ src=[{gN:"PCI_Header", gS: PCIHEAD, gE:PCIHEAD+0x3f, gD:" PCI header emulation w
[{ fT:RO, fC:0, fD:"Not Implemented"}]}, [{ fT:RO, fC:0, fD:"Not Implemented"}]},
{rN:"CAP2", rS:0x24, rE:0x27, rD:"HBA Capabilities Extended", rC: {rN:"CAP2", rS:0x24, rE:0x27, rD:"HBA Capabilities Extended", rC:
[{ fs: 6, fE:31, fT:RO, fC:0, fD:"Reserved"}, [{ 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:"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:"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:"SDS", fS: 3, fT:RO, fC:0, fD:"Supports Device Sleep"},
...@@ -209,12 +224,12 @@ src=[{gN:"PCI_Header", gS: PCIHEAD, gE:PCIHEAD+0x3f, gD:" PCI header emulation w ...@@ -209,12 +224,12 @@ src=[{gN:"PCI_Header", gS: PCIHEAD, gE:PCIHEAD+0x3f, gD:" PCI header emulation w
{gN:"HBA_PORT", gS: HBA_OFFS + 0x100, gE:HBA_OFFS + 0x17f, gD:"HBA Port registers",gC: {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: [{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)"}, [{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"}]}, { 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: {rN:"PxCLBU", rS:0x04, rE:0x07, rD:"Port x CLB address, upper 32 bits of 64", rC:
[{ fT:RO, fC:0, fD:"Not Implemented"}]}, [{ fT:RO, fC:0, fD:"Not Implemented"}]},
{rN:"PxFB", rS:0x8, rE:0x0b, rD:"FIS Base Address", rC: {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)"}, [{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"}]}, { 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: {rN:"PxFBU", rS:0x0c, rE:0x0f, rD:"FIS address, upper 32 bits of 64", rC:
[{ fT:RO, fC:0, fD:"Not Implemented"}]}, [{ fT:RO, fC:0, fD:"Not Implemented"}]},
{rN:"PxIS", rS:0x10, rE:0x13, rD:"Port x Interrupt Status", rC: {rN:"PxIS", rS:0x10, rE:0x13, rD:"Port x Interrupt Status", rC:
...@@ -237,26 +252,342 @@ src=[{gN:"PCI_Header", gS: PCIHEAD, gE:PCIHEAD+0x3f, gD:" PCI header emulation w ...@@ -237,26 +252,342 @@ src=[{gN:"PCI_Header", gS: PCIHEAD, gE:PCIHEAD+0x3f, gD:" PCI header emulation w
{fN:"DSS", fS: 2, fT:RWC,fC:0, fD:"DMA Setup FIS Interrupt - DMA Setup FIS received 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:"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"}]}, {fN:"DHRS", fS: 0, fT:RWC,fC:0, fD:"D2H Register FIS Interrupt - D2H Register FIS received with 'I' bit set"}]},
{rN:"PxIE", rS:0x14, rE:0x17, rD:"Port x Interrupt Enable", rC:
[{fN:"CPDE", fS:31, fT:RW, fC:0, fD:"Cold Port Detect Enable"},
{fN:"TFEE", fS:30, fT:RW, fC:0, fD:"Task File Error Enable"},
{fN:"HBFE", fS:29, fT:RW, fC:0, fD:"Host Bus (PCI) Fatal Error Enable"},
{fN:"HBDE", fS:28, fT:RW, fC:0, fD:"ECC Error R/W System Memory Enable"},
{fN:"IFE", fS:27, fT:RW, fC:0, fD:"Interface Fatal Error Enable (sect. 6.1.2)"},
{fN:"INFE", fS:26, fT:RW, fC:0, fD:"Interface Non-Fatal Error Enable (sect. 6.1.2)"},
{ fS:25, fT:RO, fC:0, fD:"Reserved"},
{fN:"OFE", fS:24, fT:RW, fC:0, fD:"Overflow Enable"},
{fN:"IPME", fS:23, fT:RW, fC:0, fD:"Incorrect Port Multiplier Enable"},
{fN:"PRCE", fS:22, fT:RO, fC:0, fD:"PhyRdy changed Enable"}, #Indirect clear
{ fS: 8, fE:21, fT:RO, fC:0, fD:"Reserved"},
{fN:"DMPE", fS: 7, fT:RO, fC:0, fD:"Device Mechanical Presence Interrupt Enable"}, #Indirect clear
{fN:"PCE", fS: 6, fT:RO, fC:0, fD:"Port Connect Change Interrupt Enable"}, #Indirect clear
{fN:"DPE", fS: 5, fT:RW, fC:0, fD:"Descriptor Processed Interrupt Enable"},
{fN:"UFE", fS: 4, fT:RO, fC:0, fD:"Unknown FIS"}, #Indirect clear
{fN:"SDBE", fS: 3, fT:RW, fC:0, fD:"Device Bits Interrupt Enable"},
{fN:"DSE", fS: 2, fT:RW, fC:0, fD:"DMA Setup FIS Interrupt Enable"},
{fN:"PSE", fS: 1, fT:RW, fC:0, fD:"PIO Setup FIS Interrupt Enable"},
{fN:"DHRE", fS: 0, fT:RW, fC:0, fD:"D2H Register FIS Interrupt Enable"}]},
{rN:"PxCMD", rS:0x18, rE:0x1b, rD:"Port x Command and Status", rC:
[{fN:"ICC", fS:28, fE:31, fT:RW, fC:0, fD:"Interface Communication Control"},
# Only act if Link Layer in L_IDLE or L_NoCommPower states
# 0x8 - DevSleep
# 0x6 - Slumber
# 0x2 - Partial
# 0x1 - Active
# 0x0 - No-Op/Idle
# All other commands reserved
{fN:"ASP", fS:27, fT:RO, fC:0, fD:"Aggressive Slumber/Partial - not implemented"},
{fN:"ALPE", fS:26, fT:RO, fC:0, fD:"Aggressive Link Power Management Enable - not implemented"},
{fN:"DLAE", fS:25, fT:RW, fC:0, fD:"Drive LED on ATAPI enable"},
{fN:"ATAPI", fS:24, fT:RW, fC:0, fD:"Device is ATAPI (for activity LED)"},
{fN:"APSTE", fS:23, fT:RW, fC:0, fD:"Automatic Partial to Slumber Transitions Enabled"},
{fN:"FBSCP", fS:22, fT:RO, fC:0, fD:"FIS-Based Switching Capable Port - not implemented"},
{fN:"ESP", fS:21, fT:RO, fC:1, fD:"External SATA port"},
{fN:"CPD", fS:20, fT:RO, fC:0, fD:"Cold Presence Detection"},
{fN:"MPSP", fS:19, fT:RO, fC:0, fD:"Mechanical Presence Switch Attached to Port"},
{fN:"HPCP", fS:18, fT:RO, fC:1, fD:"Hot Plug Capable Port"},
{fN:"PMA", fS:17, fT:RW, fC:0, fD:"Port Multiplier Attached - not implemented (software should write this bit)"},
{fN:"CPS", fS:16, fT:RO, fC:0, fD:"Cold Presence State"},
{fN:"CR", fS:15, fT:RO, fC:0, fD:"Command List Running (section 5.3.2)"},
{fN:"FR", fS:14, fT:RO, fC:0, fD:"FIS Receive Running (section 10.3.2)"},
{fN:"MPSS", fS:13, fT:RO, fC:0, fD:"Mechanical Presence Switch State"},
{fN:"CCS", fS: 8, fE:12, fT:RO, fC:0, fD:"Current Command Slot (when PxCMD.ST 1-> ) should be reset to 0, when 0->1 - highest priority is 0"},
{ fS: 5, fE: 7, fT:RO, fC:0, fD:"Reserved"},
{fN:"FRE", fS: 4, fT:RW, fC:0, fD:"FIS Receive Enable (enable after FIS memory is set)"},
{fN:"CLO", fS: 3, fT:RW1,fC:0, fD:"Command List Override"},
{fN:"POD", fS: 2, fT:RO, fC:1, fD:"Power On Device (RW with Cold Presence Detection)"},
{fN:"SUD", fS: 1, fT:RO, fC:1, fD:"Spin-Up Device (RW with Staggered Spin-Up Support)"},
{fN:"ST", fS: 0, fT:RW, fC:0, fD:"Start (HBA may process commands). See section 10.3.1"}]},
# 0x1c..0x1f - Reserved
{rN:"PxTFD", rS:0x20, rE:0x23, rD:"Port x Task File Data (copy of error/status from device)", rC:
[{ fS:16, fE:31, fT:RO, fC:0, fD:"Reserved"},
{fN:"ERR", fS: 8, fE:15, fT:RO, fC:0, fD:"Latest Copy of Task File Error Register"},
{fN:"STS", fS: 0, fE: 7, fT:RO, fC:0, fD:"Latest Copy of Task File Status Register"},
# bit 7 - BSY
# bits 6..4 - command-specific
# bit 3 - DRQ
# bits 1..2 - command-specific
# bit 0 - ERR
]},
{rN:"PxSIG", rS:0x24, rE:0x27, rD:"Port x Signature (first D2H data after reset)", rC:
[{fN:"SIG", fS: 0, fE:31, fT:RO, fC:0xffffffff, fD:"Data in the first D2H Register FIS"},
# bits 24..31 - LBA High Register
# bits 16..23 - LBA Mid Register
# bits 8..15 - LBA Low Register
# bits 0.. 7 - Sector Count Register
]},
{rN:"PxSIG", rS:0x28, rE:0x2b, rD:"Port x SATA Status (SCR0:SStatus)", rC:
[{ fS:12, fE:31, fT:RO, fC:0, fD:"Reserved"},
{fN:"IPM", fS: 8, fE:11, fT:RO, fC:0, fD:"Interface Power Management"},
# 0 - Device not present or communication not established
# 1 - Interface in active state
# 2 - Partial power state
# 6 - Slumber
# 8 - DevSleep
{fN:"SPD", fS: 4, fE: 7, fT:RO, fC:0, fD:"Interface Speed"},
# 0 - Device not present or communication not established
# 1 - Gen 1 speed
# 2 - Gen 2 speed
# 3 - Gen 3 speed
{fN:"DET", fS: 0, fE: 3, fT:RO, fC:0, fD:"Device Detection (should be detected if COMINIT is received)"},
# 0 - no device detected and Phy communication not established
# 1 - device present and detected but Phy communication not established
# 3 - device present and detected and Phy communication established
# 4 - Phy in offline mode as a result of interface being disabled or
# or running in a BIST loopback mode
]},
{rN:"PxSCTL", rS:0x2c, rE:0x2f, rD:"Port x SATA Control (SCR2:SControl)", rC:
[{ fS:20, fE:31, fT:RO, fC:0, fD:"Reserved"},
{fN:"PMP", fS:16, fE:19, fT:RO, fC:0, fD:"Port Multiplier Port - not used by AHCI"},
{fN:"SPM", fS:12, fE:15, fT:RO, fC:0, fD:"Select Power Management - not used by AHCI"},
{fN:"IPM", fS: 8, fE:11, fT:RW, fC:0, fD:"Interface Power Management Transitions Allowed"},
# 0 - no interface restrictions
# 1 - Transitions to Partial are disabled
# 2 - Transitions to Slumber are disabled
# 4 - Transitions to DevSleep are disabled
# Other bit-ORed values are possible
{fN:"SPD", fS: 4, fE: 7, fT:RO, fC:0, fD:"Interface Highest Speed"},
# 0 - No Speed Limit
# 1 - Gen 1 speed only
# 2 - Gen 2 speed or less
# 3 - Gen 3 speed or less
{fN:"DET", fS: 0, fE: 3, fT:RO, fC:0, fD:"Device Detection Initialization"},
# 0 - no device detection/initialization requested
# 1 - Perform interface initialization (same as hard reset)
# 4 - Disable SATA and put PHY in offline mode
]},
{rN:"PxSERR", rS:0x30, rE:0x34, rD:"Port x SATA Error (SCR1:SError)", rC:
[{ fS:27, fE:31, fT:RO, fC:0, fD:"Reserved"},
{fN:"DIAD.X",fS:26, fT:RWC,fC:0, fD:"Exchanged (set on COMINIT), reflected in PxIS.PCS"},
{fN:"DIAD.F",fS:25, fT:RWC,fC:0, fD:"Unknown FIS"},
{fN:"DIAD.T",fS:24, fT:RWC,fC:0, fD:"Transport state transition error"},
{fN:"DIAD.S",fS:23, fT:RWC,fC:0, fD:"Link sequence error"},
{fN:"DIAD.H",fS:22, fT:RWC,fC:0, fD:"Handshake Error (i.e. Device got CRC error)"},
{fN:"DIAD.C",fS:21, fT:RWC,fC:0, fD:"CRC error in Link layer"},
{fN:"DIAD.D",fS:20, fT:RWC,fC:0, fD:"Disparity Error - not used by AHCI"},
{fN:"DIAD.B",fS:19, fT:RWC,fC:0, fD:"10B to 8B decode error"},
{fN:"DIAD.W",fS:18, fT:RWC,fC:0, fD:"COMMWAKE signal was detected"},
{fN:"DIAD.I",fS:17, fT:RWC,fC:0, fD:"PHY Internal Error"},
{fN:"DIAD.N",fS:16, fT:RWC,fC:0, fD:"PhyRdy changed. Reflected in PxIS.PRCS bit."},
{ fS:12, fE:15, fT:RO, fC:0, fD:"Reserved"},
{fN:"ERR.E", fS:11, fT:RWC,fC:0, fD:"Internal Error"},
{fN:"ERR.P", fS:10, fT:RWC,fC:0, fD:"Protocol Error - a violation of SATA protocol detected"},
{fN:"ERR.C", fS: 9, fT:RWC,fC:0, fD:"Persistent Communication or Data Integrity Error"},
{fN:"ERR.T", fS: 8, fT:RWC,fC:0, fD:"Transient Data Integrity Error (error not recovered by the interface)"},
{ fS: 2, fE: 7, fT:RO, fC:0, fD:"Reserved"},
{fN:"ERR.M", fS: 1, fT:RWC,fC:0, fD:"Communication between the device and host was lost but re-established"},
{fN:"ERR.I", fS: 1, fT:RWC,fC:0, fD:"Recovered Data integrity Error"}
]},
{rN:"PxSACT", rS:0x34, rE:0x37, rD:"Port x SATA Active (SCR3:SActive), only set when PxCMD.ST==1", rC:
[{fN:"DS", fT:RW1,fC:0, fD:"Device Status: bit per Port, for TAG in native queued command"}
]},
{rN:"PxCI", rS:0x38, rE:0x3b, rD:"Port x Command Issue", rC:
[{fN:"CI", fT:RW1,fC:0, fD:"Command Issued: bit per Port, only set when PxCMD.ST==1, also cleared by PxCMD.ST: 1->0 by soft"}
]},
{rN:"PxSNTF", rS:0x3c, rE:0x3f, rD:"Port x SATA Notification (SCR4:SNotification)", rC:
[{ fS:16, fE:31, fT:RO, fC:0, fD:"Reserved"},
{fN:"PMN", fS: 0, fE:15, fT:RWC,fC:0, fD:"PM Notify (bit per PM port)"}
]},
{rN:"PxFBS", rS:0x40, rE:0x43, rD:"Port x FIS-based switching control)", rC:
[{ fS:20, fE:31, fT:RO, fC:0, fD:"Reserved"},
{fN:"DWE", fS:16, fE:19, fT:RO, fC:0, fD:"Device with Error"},
{fN:"ADO", fS:12, fE:15, fT:RO, fC:0, fD:"Active Device Optimization"},
{fN:"DEV", fS: 8, fE:11, fT:RW, fC:0, fD:"Device To Issue"},
{ fS: 3, fE: 7, fT:RO, fC:0, fD:"Reserved"},
{fN:"SDE", fS: 2, fT:RO, fC:0, fD:"Single Device Error"},
{fN:"DEC", fS: 1, fT:RW1,fC:0, fD:"Device Error Clear"},
{fN:"EN", fS: 0, fT:RW, fC:0, fD:"Enable"}
]},
{rN:"PxDEVSLP",rS:0x44, rE:0x47, rD:"Port x Device Sleep", rC:
[{ fS:29, fE:31, fT:RO, fC:0, fD:"Reserved"},
{fN:"DM", fS:25, fE:28, fT:RO, fC:0, fD:"DITO Multiplier"},
{fN:"DITO", fS:15, fE:24, fT:RW, fC:0, fD:"Device Sleep Idle Timeout (section 8.5.1.1.1)"},
{fN:"MDAT", fS:10, fE:14, fT:RW, fC:0, fD:"Minimum Device Sleep Assertion Time"},
{fN:"DETO", fS: 2, fE: 9, fT:RW, fC:0, fD:"Device Sleep Exit Timeout"},
{fN:"DSP", fS: 1, fT:RO, fC:0, fD:"Device Sleep Present"},
{fN:"ADSE", fS: 1, fT:RO, fC:0, fD:"Aggressive Device Sleep Enable"}
]},
# 0x48..0x6f - reserved
{rN:"PxVS", rS:0x70, rE:0x7f, rD:"Port x Vendor Specific", rC:
[{ fT:RW, fC:0, fD:"Vendor-specific data - 128 bits"}
]},
]}, ]},
] ]
"""
{rN:"??", rS:0x06, rE:0x7, rD:"????", rC:
[]},
VID = 0xfffe # What to use for non-PCI "vendorID"?
DID = 0x0001
SSVID = 0xfffe reg_defaults = [0]*4096 # array of bytes, default value = 0
SSID = 0x0001 bit_types = [0]*2048 # array of words, default value = 0
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? for group in src:
HBA_OFFS = 0x0 groupName = group[gN]
#HBA_PORT0 = 0x100 Not needed, always HBA_OFFS + 0x100 groupStart = group[gS]
PCIHEAD = 0x180 groupEnd = group[gE]
PMCAP = 0x1C0 if groupStart > groupEnd:
ABAR = 0x80000000 + HBA_OFFS groupEnd, groupStart = (groupStart, groupEnd)
P0CLB = 0x0 # Port 0 CLB address - define here? try:
""" groupDescription= group[gD]
\ No newline at end of file except:
groupDescription= ""
print ("Group %s (%s) 0x%x..0x%x:"%(groupName, groupDescription, groupStart, groupEnd))
for dataRange in group[gC]:
try:
rangeName = dataRange[rN]
except:
rangeName = ""
if (not rS in dataRange) and (not rE in dataRange):
rangeStart = 0
rangeEnd = groupEnd - groupStart -1
else:
try:
rangeStart = dataRange[rS]
except:
rangeStart = dataRange[rE]
try:
rangeEnd = dataRange[rE]
except:
rangeEnd = dataRange[rS]
if rangeStart > rangeEnd:
rangeEnd, rangeStart = (rangeStart, rangeEnd)
try:
rangeDescription= dataRange[rD]
except:
rangeDescription= ""
print (" Range %s (%s) 0x%x..0x%x:"%(rangeName, rangeDescription, rangeStart, rangeEnd))
for dataField in dataRange[rC]:
try:
fieldName = dataField[fN]
except:
fieldName = ""
if (not fS in dataField) and (not fE in dataField):
fieldStart = 0
fieldEnd = (rangeEnd - rangeStart) * 8 +7 # last bit in bytes
else:
try:
fieldStart = dataField[fS]
except:
fieldStart = dataField[fE]
try:
fieldEnd = dataField[fE]
except:
fieldEnd = dataField[fS]
if fieldStart > fieldEnd:
fieldEnd, fieldStart = (fieldStart, fieldEnd)
try:
fieldDescription= dataField[fD]
except:
fieldDescription= ""
try:
fieldValue = dataField[fC]
except:
fieldValue = 0
print (" Field %s %d..%d, value = 0x%x, type = %s (%s)"%(fieldName, fieldStart, fieldEnd, fieldValue, dataField[fT], fieldDescription))
# Split field in bytes
offs=groupStart+rangeStart
fv = fieldValue << fieldStart
if dataField[fT] == RO:
t = 0
elif dataField[fT] == RW:
t = 1
elif dataField[fT] == RWC:
t = 2
elif dataField[fT] == RW1:
t = 3
else:
raise("ERROR: Invalid field type %s, only RO, RW, RWC and RX1 are valid"%(dataField[fT]))
ft=0
for i in range(fieldEnd - fieldStart +1):
ft = (ft << 2) | t
ft <<= (2*fieldStart)
for b in range (fieldStart//8, fieldEnd//8 + 1):
if (b > 0):
bs=0
else:
bs = fieldStart % 8
if (b < fieldEnd//8):
be = 7
else:
be = fieldEnd%8
bm = 0;
for i in range (bs,be+1):
bm |= (1 << i)
bv = (fv >> (8*b)) & 0xff
bt = (ft >> (16*b)) & 0xffff
bm16 = 0;
for i in range (bs,be+1):
bm16 |= (3 << (2*i))
# print ("fS = 0x%x, fE=0x%x, fS//8 = 0x%x, fE//8 + 1 = 0x%x, b=%d, fieldValue=0x%x, bv=0x%x"%(fieldStart, fieldEnd, fieldStart//8,(fieldEnd//8) + 1,b, fieldValue, bv))
reg_defaults[offs+b] = ((reg_defaults[offs+b] ^ bv) & bm) ^ reg_defaults[offs+b]
print ("reg_defaults[0x%x] = 0x%x"%(offs+b,reg_defaults[offs+b]))
#bit_types
if (offs+b) < len(bit_types):
bit_types[offs+b] = ((bit_types[offs+b] ^ bt) & bm16) ^ bit_types[offs+b]
print ("bit_types[0x%x] = 0x%x"%(offs+b,bit_types[offs+b]))
def create_no_parity (init_data, # numeric data
num_bits, # number of bits in item
start_bit, # bit number to start filling from
full_bram): # true if ramb36, false - ramb18
bsize = (0x4000,0x8000)[full_bram]
bdata = [0 for i in range(bsize)]
for item in init_data:
for bt in range (num_bits):
bdata[start_bit+bt] = (item >> bt) & 1;
start_bit += num_bits
data = []
for i in range (len(bdata)//256):
d = 0;
for b in range(255, -1,-1):
d = (d<<1) + bdata[256*i+b]
data.append(d)
# print(bdata)
# print(data)
return {'data':data,'data_p':[]}
def print_params(data,out_file_name):
with open(out_file_name,"w") as out_file:
for i, v in enumerate(data['data']):
if v:
print (", .INIT_%02X (256'h%064X)"%(i,v), file=out_file)
# if (include_parity):
for i, v in enumerate(data['data_p']):
if v:
print (", .INITP_%02X (256'h%064X)"%(i,v), file=out_file)
import os
#print (os.path.abspath(__file__))
#print (os.path.dirname(__file__))
#print (os.path.join(os.path.dirname(__file__), reg_defaults_path))
#print (os.path.abspath(os.path.join(os.path.dirname(__file__), reg_defaults_path)))
#print(reg_defaults)
#print("\n-------------------------\n")
#print(create_no_parity(reg_defaults, 8, 0, True))
#print("\n-------------------------\n")
#print(bit_types)
#print("\n-------------------------\n")
#print(create_no_parity(bit_types, 16, 0, True))
print_params(create_no_parity(reg_defaults, 8, 0, True),os.path.abspath(os.path.join(os.path.dirname(__file__), reg_defaults_path)))
print ("AHCI register defaults are written to %s"%(os.path.abspath(os.path.join(os.path.dirname(__file__), reg_defaults_path))))
print_params(create_no_parity(bit_types, 16, 0, True),os.path.abspath(os.path.join(os.path.dirname(__file__), reg_types_path)))
print ("AHCI register bit field types are written to %s"%(os.path.abspath(os.path.join(os.path.dirname(__file__), reg_types_path))))
, .INIT_00 (256'h0000000000000000000000000001030100000001000000008000000000240020)
, .INIT_08 (256'h000000000024000600000000000000000000000080000C000000000080000800)
, .INIT_09 (256'h000000000000000000000000000000000000000000000000FFFFFFFF00000000)
, .INIT_0C (256'h000000000000000000000000000000000000000001010001001000000001FFFE)
, .INIT_0D (256'h000001000000000000000040000000000001FFFE000000008000000000000000)
, .INIT_0E (256'h0000000000000000000000000000000000000000000000000000000040000001)
, .INIT_00 (256'h0000000000000000AAAAAAAAAAAAAAAA00000000000000070000000000000000)
, .INIT_10 (256'h0000000000000000555555555555000000000000000000005555555555500000)
, .INIT_11 (256'h000000000000000055054004000001C15551400000000455AAA28000000008AA)
, .INIT_12 (256'h0000000000550000000000000000000000000000000000000000000000000000)
, .INIT_13 (256'h00000000AAAAAAAAFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF002AAAAA00AA0008)
, .INIT_14 (256'h000000000000000000000000000000000001555555555550000000000055000D)
, .INIT_17 (256'h5555555555555555555555555555555555555555555555555555555555555555)
, .INIT_18 (256'h00000000000055550000000000000000AA820000001000140000000000000000)
, .INIT_1B (256'h0000000000005555000000000000000000000000000000000000000000000000)
, .INIT_1C (256'h0000000000000000000000000000000000000000800100050000000000000000)
...@@ -25,7 +25,8 @@ ...@@ -25,7 +25,8 @@
module axi_ahci_regs#( module axi_ahci_regs#(
parameter ADDRESS_BITS = 8 // number of memory address bits // parameter ADDRESS_BITS = 8 // number of memory address bits
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 aclk, // clock - should be buffered input aclk, // clock - should be buffered
input arst, // @aclk sync reset, active high input arst, // @aclk sync reset, active high
...@@ -84,7 +85,7 @@ module axi_ahci_regs#( ...@@ -84,7 +85,7 @@ module axi_ahci_regs#(
output [31:0] hba_dout output [31:0] hba_dout
); );
wire [ADDRESS_BITS-1:0] bram_waddr; wire [ADDRESS_BITS-1:0] bram_waddr;
wire [ADDRESS_BITS-1:0] pre_awaddr; // wire [ADDRESS_BITS-1:0] pre_awaddr;
wire [ADDRESS_BITS-1:0] bram_raddr; wire [ADDRESS_BITS-1:0] bram_raddr;
wire [31:0] bram_rdata; wire [31:0] bram_rdata;
wire pre_bram_wen; // one cycle ahead of bram_wen, nut not masked by dev_ready wire pre_bram_wen; // one cycle ahead of bram_wen, nut not masked by dev_ready
...@@ -101,12 +102,17 @@ module axi_ahci_regs#( ...@@ -101,12 +102,17 @@ module axi_ahci_regs#(
wire write_busy_w = write_busy_r || write_start_burst; wire write_busy_w = write_busy_r || write_start_burst;
reg [31:0] bram_wdata_r; reg [31:0] bram_wdata_r;
reg [31:0] bram_rdata_r; reg [31:0] bram_rdata_r;
reg bram_wen_d; // reg bram_wen_d;
wire [63:0] regbit_type; wire [63:0] regbit_type;
wire [31:0] ahci_regs_di; 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]}}}; reg [ 3:0] bram_wstb_r;
reg bram_wen_r;
assign bram_addr = bram_ren[0] ? bram_raddr : (bram_wen ? bram_waddr : pre_awaddr); // wire [31:0] wmask = {{8{bram_wstb[3]}},{8{bram_wstb[2]}},{8{bram_wstb[1]}},{8{bram_wstb[0]}}};
wire [31:0] wmask = {{8{bram_wstb_r[3]}},{8{bram_wstb_r[2]}},{8{bram_wstb_r[1]}},{8{bram_wstb_r[0]}}};
reg [ADDRESS_BITS-1:0] bram_waddr_r;
wire high_sel = bram_waddr_r[ADDRESS_BITS-1]; // high addresses - use single-cycle writes without read-modify-write
// 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);
always @(posedge aclk) begin always @(posedge aclk) begin
if (arst) write_busy_r <= 0; if (arst) write_busy_r <= 0;
else if (write_start_burst) write_busy_r <= 1; else if (write_start_burst) write_busy_r <= 1;
...@@ -115,18 +121,24 @@ module axi_ahci_regs#( ...@@ -115,18 +121,24 @@ module axi_ahci_regs#(
if (bram_wen) bram_wdata_r <= bram_wdata; if (bram_wen) bram_wdata_r <= bram_wdata;
if (bram_ren[1]) bram_rdata_r <= bram_rdata; if (bram_ren[1]) bram_rdata_r <= bram_rdata;
bram_wen_d <= bram_wen;
bram_wstb_r <= {4{bram_wen}} & bram_wstb;
bram_wen_r <= bram_wen;
if (bram_wen) bram_waddr_r <= bram_waddr;
end end
generate generate
genvar i; genvar i;
for (i=0; i < 32; i=i+1) begin: bit_type_block for (i=0; i < 32; i=i+1) begin: bit_type_block
assign ahci_regs_di[i] = (regbit_type[2*i+1] && wmask[i])? assign ahci_regs_di[i] = (regbit_type[2*i+1] && wmask[i] && !high_sel)?
((regbit_type[2*i] && wmask[i])? ((regbit_type[2*i] && wmask[i])?
(bram_rdata[i] || bram_wdata_r[i]): // 3: RW1 (bram_rdata[i] || bram_wdata_r[i]): // 3: RW1
(bram_rdata[i] && !bram_wdata_r[i])): // 2: RWC (bram_rdata[i] && !bram_wdata_r[i])): // 2: RWC
((regbit_type[2*i] && wmask[i])? (((regbit_type[2*i] && wmask[i]) || high_sel)?
(bram_wdata_r[i]): // 1: RW write new data (bram_wdata_r[i]): // 1: RW write new data - get here for high_sel
(bram_rdata[i])); // 0: R0 (keep old data) (bram_rdata[i])); // 0: R0 (keep old data)
end end
endgenerate endgenerate
...@@ -153,7 +165,7 @@ module axi_ahci_regs#( ...@@ -153,7 +165,7 @@ module axi_ahci_regs#(
.bready (bready), // input .bready (bready), // input
.bid (bid), // output[11:0] .bid (bid), // output[11:0]
.bresp (bresp), // output[1:0] .bresp (bresp), // output[1:0]
.pre_awaddr (pre_awaddr), // output[9:0] .pre_awaddr (), //pre_awaddr), // output[9:0]
.start_burst (write_start_burst), // output .start_burst (write_start_burst), // output
// .dev_ready (!nowrite && !bram_ren[0]), // input // .dev_ready (!nowrite && !bram_ren[0]), // input
.dev_ready (!bram_wen), // input There will be no 2 bram_wen in a row .dev_ready (!bram_wen), // input There will be no 2 bram_wen in a row
...@@ -193,33 +205,37 @@ module axi_ahci_regs#( ...@@ -193,33 +205,37 @@ module axi_ahci_regs#(
.bram_rdata (bram_rdata_r) // input[31:0] .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} ; // Register memory, lower half uses read-modify-write using bit type from ahci_regs_type_i ROM, 2 aclk cycles/per write and
wire [ 9:0] bram_addr_ext = (ADDRESS_BITS == 10)? bram_addr: {{(10-ADDRESS_BITS){1'b0}}, bram_addr} ; // high addresses half are just plain write registers, they heve single-cycle write
wire [ 8:0] brom_addr_ext = (ADDRESS_BITS == 9)? bram_addr: {{(9-ADDRESS_BITS){1'b0}}, bram_addr} ; // Only low registers write generates cross-clock writes over the FIFO.
// All registers can be accessed in byte/word/dword mode over the AXI
// Lower registers are used as AHCI memory registers, high - for AHCI command list(s), to eliminate the need to update transfer count
// in the system memory.
ramt_var_w_var_r #( ramt_var_wb_var_r #(
.REGISTERS_A (0), .REGISTERS_A (0),
.REGISTERS_B (1), .REGISTERS_B (1),
.LOG2WIDTH_A (5), .LOG2WIDTH_A (5),
.LOG2WIDTH_B (5), .LOG2WIDTH_B (5),
.WRITE_MODE_A("NO_CHANGE"), .WRITE_MODE_A("NO_CHANGE"),
.WRITE_MODE_B("NO_CHANGE") .WRITE_MODE_B("NO_CHANGE")
// TODO: include here init (default values) `include "includes/ahci_defaults.vh"
) ahci_regs_i ( ) ahci_regs_i (
.clk_a (aclk), // input .clk_a (aclk), // input
.addr_a (bram_addr_ext), // input[9:0] .addr_a (bram_addr), // input[9:0]
.en_a (bram_ren[0] || write_busy_w), // input .en_a (bram_ren[0] || write_busy_w), // input
.regen_a (1'b0), // input .regen_a (1'b0), // input
// .we_a (write_busy_r && !nowrite), // input // .we_a (write_busy_r && !nowrite), // input
.we_a (bram_wen_d), // input .we_a (bram_wstb_r), //bram_wen_d), // input[3:0]
// //
.data_out_a (bram_rdata), // output[31:0] .data_out_a (bram_rdata), // output[31:0]
.data_in_a (ahci_regs_di), // input[31:0] .data_in_a (ahci_regs_di), // input[31:0]
.clk_b (hba_clk), // input .clk_b (hba_clk), // input
.addr_b (hba_addr_ext), // input[9:0] .addr_b (hba_addr), // input[9:0]
.en_b (hba_we || hba_re[0]), // input .en_b (hba_we || hba_re[0]), // input
.regen_b (hba_re[1]), // input .regen_b (hba_re[1]), // input
.we_b (hba_we), // input .we_b ({4{hba_we}}), // input
.data_out_b (hba_dout), // output[31:0] .data_out_b (hba_dout), // output[31:0]
.data_in_b (hba_din) // input[31:0] .data_in_b (hba_din) // input[31:0]
); );
...@@ -229,11 +245,11 @@ module axi_ahci_regs#( ...@@ -229,11 +245,11 @@ module axi_ahci_regs#(
.LOG2WIDTH_WR (6), .LOG2WIDTH_WR (6),
.LOG2WIDTH_RD (6), .LOG2WIDTH_RD (6),
.DUMMY(0) .DUMMY(0)
// TODO: include here init (register bit types (RO, RW, RWC, RW1) `include "includes/ahci_types.vh"
) ahci_regs_type_i ( ) ahci_regs_type_i (
.rclk (aclk), // input .rclk (aclk), // input
.raddr (brom_addr_ext), // input[8:0] .raddr (bram_addr[8:0]), // input[8:0]
.ren (bram_wen), // input .ren (bram_wen && !bram_addr[9]), // input
.regen (1'b0), // input .regen (1'b0), // input
.data_out (regbit_type), // output[63:0] .data_out (regbit_type), // output[63:0]
.wclk (1'b0), // input .wclk (1'b0), // input
...@@ -252,7 +268,7 @@ module axi_ahci_regs#( ...@@ -252,7 +268,7 @@ module axi_ahci_regs#(
.wrst (arst), // input .wrst (arst), // input
.rclk (hba_clk), // input .rclk (hba_clk), // input
.wclk (aclk), // input .wclk (aclk), // input
.we (bram_wen_d), // input .we (bram_wen_r && !high_sel), // input
.re (soft_write_en), // input .re (soft_write_en), // input
.data_in ({bram_addr, ahci_regs_di}), // input[15:0] .data_in ({bram_addr, ahci_regs_di}), // input[15:0]
.data_out ({soft_write_addr,soft_write_data}), // output[15:0] .data_out ({soft_write_addr,soft_write_data}), // output[15:0]
......
/*******************************************************************************
* Module: ramt_var_wb_var_r
* Date:2015-05-29
* Author: Andrey Filippov
* Description: Dual port memory wrapper, with variable width write (with mask) and variable
* width read, using "TDP" mode of RAMB36E1. Same R/W widths in each port.
* Does not use parity bits to increase total data width, width down to 1 are valid.
*
* Copyright (c) 2015 Elphel, Inc.
* ramt_var_wb_var_r.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.
*
* ramt_var_wb_var_r.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/> .
*
* Additional permission under GNU GPL version 3 section 7:
* If you modify this Program, or any covered work, by linking or combining it
* with independent modules provided by the FPGA vendor only (this permission
* does not extend to any 3-rd party modules, "soft cores" or macros) under
* different license terms solely for the purpose of generating binary "bitstream"
* files and/or simulating the code, the copyright holders of this Program give
* you the right to distribute the covered work without those independent modules
* as long as the source code for them is available from the FPGA vendor free of
* charge, and there is no dependence on any encrypted modules for simulating of
* the combined code. This permission applies to you if the distributed code
* contains all the components and scripts required to completely simulate it
* with at least one of the Free Software programs.
*******************************************************************************/
`timescale 1ns/1ps
`include "system_defines.vh"
/*
Address/data widths
Connect unused data to 1b0, unused addresses - to 1'b1
RAMB18E1 in True Dual Port (TDP) Mode - each port individually
+-----------+---------+---------+---------+
|Data Width | Address | Data | Parity |
+-----------+---------+---------+---------+
| 1 | A[13:0] | D[0] | --- |
| 2 | A[13:1] | D[1:0] | --- |
| 4 | A[13:2] | D[3:0[ | --- |
| 9 | A[13:3] | D[7:0] | DP[0] |
| 18 | A[13:4] | D[15:0] | DP[1:0] |
+-----------+---------+---------+---------+
RAMB18E1 in Simple Dual Port (SDP) Mode
one of the ports (r or w) - 32/36 bits, other - variable
+------------+---------+---------+---------+
|Data Widths | Address | Data | Parity |
+------------+---------+---------+---------+
| 32/ 1 | A[13:0] | D[0] | --- |
| 32/ 2 | A[13:1] | D[1:0] | --- |
| 32/ 4 | A[13:2] | D[3:0[ | --- |
| 36/ 9 | A[13:3] | D[7:0] | DP[0] |
| 36/ 18 | A[13:4] | D[15:0] | DP[1:0] |
| 36/ 36 | A[13:5] | D[31:0] | DP[3:0] |
+------------+---------+---------+---------+
RAMB36E1 in True Dual Port (TDP) Mode - each port individually
+-----------+---------+---------+---------+
|Data Width | Address | Data | Parity |
+-----------+---------+---------+---------+
| 1 | A[14:0] | D[0] | --- |
| 2 | A[14:1] | D[1:0] | --- |
| 4 | A[14:2] | D[3:0[ | --- |
| 9 | A[14:3] | D[7:0] | DP[0] |
| 18 | A[14:4] | D[15:0] | DP[1:0] |
| 36 | A[14:5] | D[31:0] | DP[3:0] |
|1(Cascade) | A[15:0] | D[0] | --- |
+-----------+---------+---------+---------+
RAMB36E1 in Simple Dual Port (SDP) Mode
one of the ports (r or w) - 64/72 bits, other - variable
+------------+---------+---------+---------+
|Data Widths | Address | Data | Parity |
+------------+---------+---------+---------+
| 64/ 1 | A[14:0] | D[0] | --- |
| 64/ 2 | A[14:1] | D[1:0] | --- |
| 64/ 4 | A[14:2] | D[3:0[ | --- |
| 64/ 9 | A[14:3] | D[7:0] | DP[0] |
| 64/ 18 | A[14:4] | D[15:0] | DP[1:0] |
| 64/ 36 | A[14:5] | D[31:0] | DP[3:0] |
| 64/ 72 | A[14:6] | D[63:0] | DP[7:0] |
+------------+---------+---------+---------+
*/
module ramt_var_wb_var_r
#(
parameter integer REGISTERS_A = 0, // 1 - registered output
parameter integer REGISTERS_B = 0, // 1 - registered output
parameter integer LOG2WIDTH_A = 5, // WIDTH= 9 << (LOG2WIDTH - 3)
parameter integer LOG2WIDTH_B = 5, // WIDTH= 9 << (LOG2WIDTH - 3)
parameter WRITE_MODE_A = "NO_CHANGE", //Valid: "WRITE_FIRST", "READ_FIRST", "NO_CHANGE"
parameter WRITE_MODE_B = "NO_CHANGE" //Valid: "WRITE_FIRST", "READ_FIRST", "NO_CHANGE"
`ifdef PRELOAD_BRAMS
,
`include "includes/ram36_declare_init.vh"
`endif
)(
input clk_a, // clock for port A
input [14-LOG2WIDTH_A:0] addr_a, // address port A
input en_a, // enable port A (read and write)
input regen_a, // output register enable port A
// input [((LOG2WIDTH_A > 3)? (LOG2WIDTH_A-3):0):0] we_a, // write port enable port A
input [((LOG2WIDTH_A > 3)? ((LOG2WIDTH_A > 4)?3:1):0):0] we_a, // write port enable port A
output [(1 << LOG2WIDTH_A)-1:0] data_out_a,// data out port A
input [(1 << LOG2WIDTH_A)-1:0] data_in_a, // data in port A
input clk_b, // clock for port BA
input [14-LOG2WIDTH_B:0] addr_b, // address port B
input en_b, // read enable port B
input regen_b, // output register enable port B
// input [((LOG2WIDTH_B > 3)? (LOG2WIDTH_B-3):0):0] we_b, // write port enable port B
input [((LOG2WIDTH_B > 3)? ((LOG2WIDTH_B > 4)?3:1):0):0] we_b, // write port enable port B
output [(1 << LOG2WIDTH_B)-1:0] data_out_b,// data out port B
input [(1 << LOG2WIDTH_B)-1:0] data_in_b // data in port B
);
localparam PWIDTH_A = (LOG2WIDTH_A > 2)? (9 << (LOG2WIDTH_A - 3)): (1 << LOG2WIDTH_A);
localparam PWIDTH_B = (LOG2WIDTH_B > 2)? (9 << (LOG2WIDTH_B - 3)): (1 << LOG2WIDTH_B);
localparam WIDTH_A = 1 << LOG2WIDTH_A;
localparam WIDTH_B = 1 << LOG2WIDTH_B;
wire [31:0] data_out32_a;
assign data_out_a=data_out32_a[WIDTH_A-1:0];
wire [31:0] data_out32_b;
assign data_out_b=data_out32_b[WIDTH_B-1:0];
wire [WIDTH_A+31:0] data_in_ext_a = {32'b0,data_in_a[WIDTH_A-1:0]};
wire [31:0] data_in32_a = data_in_ext_a[31:0];
wire [WIDTH_B+31:0] data_in_ext_b = {32'b0,data_in_b[WIDTH_B-1:0]};
wire [31:0] data_in32_b = data_in_ext_b[31:0];
wire [3:0] we_a4= (LOG2WIDTH_A > 3)? ((LOG2WIDTH_A > 4)? we_a : {2{we_a}} ):{4{we_a}};
wire [3:0] we_b4= (LOG2WIDTH_B > 3)? ((LOG2WIDTH_B > 4)? we_a : {2{we_b}} ):{4{we_b}};
RAMB36E1
#(
.RSTREG_PRIORITY_A ("RSTREG"), // Valid: "RSTREG" or "REGCE"
.RSTREG_PRIORITY_B ("RSTREG"), // Valid: "RSTREG" or "REGCE"
.DOA_REG (REGISTERS_A), // Valid: 0 (no output registers) and 1 - one output register (in SDP - to lower 36)
.DOB_REG (REGISTERS_B), // Valid: 0 (no output registers) and 1 - one output register (in SDP - to lower 36)
.RAM_EXTENSION_A ("NONE"), // Cascading, valid: "NONE","UPPER", LOWER"
.RAM_EXTENSION_B ("NONE"), // Cascading, valid: "NONE","UPPER", LOWER"
.READ_WIDTH_A (PWIDTH_A), // Valid: 0,1,2,4,9,18,36 and in SDP mode - 72 (should be 0 if port is not used)
.READ_WIDTH_B (PWIDTH_B), // Valid: 0,1,2,4,9,18,36 and in SDP mode - 72 (should be 0 if port is not used)
.WRITE_WIDTH_A (PWIDTH_A), // Valid: 0,1,2,4,9,18,36 and in SDP mode - 72 (should be 0 if port is not used)
.WRITE_WIDTH_B (PWIDTH_B), // Valid: 0,1,2,4,9,18,36 and in SDP mode - 72 (should be 0 if port is not used)
.RAM_MODE ("TDP"), // Valid "TDP" (true dual-port) and "SDP" - simple dual-port
.WRITE_MODE_A (WRITE_MODE_A), // Valid: "WRITE_FIRST", "READ_FIRST", "NO_CHANGE"
.WRITE_MODE_B (WRITE_MODE_B), // Valid: "WRITE_FIRST", "READ_FIRST", "NO_CHANGE"
.RDADDR_COLLISION_HWCONFIG ("DELAYED_WRITE"),// Valid: "DELAYED_WRITE","PERFORMANCE" (no access to the same page)
.SIM_COLLISION_CHECK ("ALL"), // Valid: "ALL", "GENERATE_X_ONLY", "NONE", and "WARNING_ONLY"
.INIT_FILE ("NONE"), // "NONE" or filename with initialization data
.SIM_DEVICE ("7SERIES"), // Simulation device family - "VIRTEX6", "VIRTEX5" and "7_SERIES" // "7SERIES"
.EN_ECC_READ ("FALSE"), // Valid:"FALSE","TRUE" (ECC decoder circuitry)
.EN_ECC_WRITE ("FALSE") // Valid:"FALSE","TRUE" (ECC decoder circuitry)
`ifdef PRELOAD_BRAMS
`include "includes/ram36_pass_init.vh"
`endif
) RAMB36E1_i
(
// Port A (Read port in SDP mode):
.DOADO (data_out32_a), // Port A data/LSB data[31:0], output
.DOPADOP (), // Port A parity/LSB parity[3:0], output
.DIADI (data_in32_a), // Port A data/LSB data[31:0], input
.DIPADIP (4'b0), // Port A parity/LSB parity[3:0], input
.ADDRARDADDR ({1'b1,addr_a,{LOG2WIDTH_A{1'b1}}}), // Port A (read port in SDP) address [15:0]. used from [14] down, unused should be high, input
.CLKARDCLK (clk_a), // Port A (read port in SDP) clock, input
.ENARDEN (en_a), // Port A (read port in SDP) Enable, input
.REGCEAREGCE (regen_a), // Port A (read port in SDP) register enable, input
.RSTRAMARSTRAM (1'b0), // Port A (read port in SDP) set/reset, input
.RSTREGARSTREG (1'b0), // Port A (read port in SDP) register set/reset, input
.WEA (we_a4), // Port A (read port in SDP) Write Enable[3:0], input
// Port B
.DOBDO (data_out32_b), // Port B data/MSB data[31:0], output
.DOPBDOP (), // Port B parity/MSB parity[3:0], output
.DIBDI (data_in32_b), // Port B data/MSB data[31:0], input
.DIPBDIP (4'b0), // Port B parity/MSB parity[3:0], input
.ADDRBWRADDR ({1'b1,addr_b,{LOG2WIDTH_B{1'b1}}}), // Port B (write port in SDP) address [15:0]. used from [14] down, unused should be high, input
.CLKBWRCLK (clk_b), // Port B (write port in SDP) clock, input
.ENBWREN (en_b), // Port B (write port in SDP) Enable, input
.REGCEB (regen_b), // Port B (write port in SDP) register enable, input
.RSTRAMB (1'b0), // Port B (write port in SDP) set/reset, input
.RSTREGB (1'b0), // Port B (write port in SDP) register set/reset, input
.WEBWE ({4'b0,we_b4}),// Port B (write port in SDP) Write Enable[7:0], input
// Error correction circuitry
.SBITERR (), // Single bit error status, output
.DBITERR (), // Double bit error status, output
.ECCPARITY (), // Genearted error correction parity [7:0], output
.RDADDRECC (), // ECC read address[8:0], output
.INJECTSBITERR (1'b0), // inject a single-bit error, input
.INJECTDBITERR (1'b0), // inject a double-bit error, input
// Cascade signals to create 64Kx1
.CASCADEOUTA (), // A-port cascade, output
.CASCADEOUTB (), // B-port cascade, output
.CASCADEINA (1'b0), // A-port cascade, input
.CASCADEINB (1'b0) // B-port cascade, input
);
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