diff --git a/test/spd_data/MT18KSF1G72HZ-1G4E2.csv b/test/spd_data/MT18KSF1G72HZ-1G4E2.csv new file mode 100644 index 0000000..76c5e16 --- /dev/null +++ b/test/spd_data/MT18KSF1G72HZ-1G4E2.csv @@ -0,0 +1,76 @@ +Part Number,Byte Number,Byte Description,Byte Value +MT18KSF1G72HZ-1G4E2,0,DDR3-CRC RANGE; EEPROM BYTES; BYTES USED,92 +MT18KSF1G72HZ-1G4E2,1,DDR3-SPD REVISON,13 +MT18KSF1G72HZ-1G4E2,2,DDR3-DRAM DEVICE TYPE,0B +MT18KSF1G72HZ-1G4E2,3,DDR3-MODULE TYPE (FORM FACTOR),08 +MT18KSF1G72HZ-1G4E2,4,DDR3-SDRAM DEVICE DENSITY BANKS,04 +MT18KSF1G72HZ-1G4E2,5,DDR3-SDRAM DEVICE ROW COLUMN COUNT,21 +MT18KSF1G72HZ-1G4E2,6,DDR3-MODULE NOMINAL VDD,02 +MT18KSF1G72HZ-1G4E2,7,DDR3-MODULE RANKS DEVICE DQ COUNT,09 +MT18KSF1G72HZ-1G4E2,8,DDR3-ECC TAG MODULE MEMORY BUS WIDTH,0B +MT18KSF1G72HZ-1G4E2,9,DDR3-FINE TIMEBASE DIVIDEND/DIVISOR,11 +MT18KSF1G72HZ-1G4E2,10,DDR3-MEDIUM TIMEBASE DIVIDEND,01 +MT18KSF1G72HZ-1G4E2,11,DDR3-MEDIUM TIMEBASE DIVISOR,08 +MT18KSF1G72HZ-1G4E2,12,DDR3-MIN SDRAM CYCLE TIME (TCKMIN),0C +MT18KSF1G72HZ-1G4E2,13,DDR3-BYTE 13 RESERVED,00 +MT18KSF1G72HZ-1G4E2,14,DDR3-CAS LATENCIES SUPPORTED (CL4 => CL11),7E +MT18KSF1G72HZ-1G4E2,15,DDR3-CAS LATENCIES SUPPORTED (CL12 => CL18),00 +MT18KSF1G72HZ-1G4E2,16,DDR3-MIN CAS LATENCY TIME (TAAMIN),69 +MT18KSF1G72HZ-1G4E2,17,DDR3-MIN WRITE RECOVERY TIME (TWRMIN),78 +MT18KSF1G72HZ-1G4E2,18,DDR3-MIN RAS# TO CAS# DELAY (TRCDMIN),69 +MT18KSF1G72HZ-1G4E2,19,DDR3-MIN ROW ACTIVE TO ROW ACTIVE DELAY (TRRDMIN),30 +MT18KSF1G72HZ-1G4E2,20,DDR3-MIN ROW PRECHARGE DELAY (TRPMIN),69 +MT18KSF1G72HZ-1G4E2,21,DDR3-UPPER NIBBLE FOR TRAS TRC,11 +MT18KSF1G72HZ-1G4E2,22,DDR3-MIN ACTIVE TO PRECHARGE DELAY (TRASMIN),20 +MT18KSF1G72HZ-1G4E2,23,DDR3-MIN ACTIVE TO ACTIVE/REFRESH DELAY (TRCMIN),89 +MT18KSF1G72HZ-1G4E2,24,DDR3-MIN REFRESH RECOVERY DELAY (TRFCMIN) LSB,20 +MT18KSF1G72HZ-1G4E2,25,DDR3-MIN REFRESH RECOVERY DELAY (TRFCMIN) MSB,08 +MT18KSF1G72HZ-1G4E2,26,DDR3-MIN INTERNAL WRITE TO READ CMD DELAY (TWTRMIN),3C +MT18KSF1G72HZ-1G4E2,27,DDR3-MIN INTERNAL READ TO PRECHARGE CMD DELAY (TRTPMIN),3C +MT18KSF1G72HZ-1G4E2,28,DDR3-MIN FOUR ACTIVE WINDOW DELAY (TFAWMIN) MSB,00 +MT18KSF1G72HZ-1G4E2,29,DDR3-MIN FOUR ACTIVE WINDOW DELAY (TFAWMIN) LSB,F0 +MT18KSF1G72HZ-1G4E2,30,DDR3-SDRAM DEVICE OUTPUT DRIVERS SUPPORTED,83 +MT18KSF1G72HZ-1G4E2,31,DDR3-SDRAM DEVICE THERMAL REFRESH OPTIONS,05 +MT18KSF1G72HZ-1G4E2,32,DDR3-MODULE THERMAL SENSOR,80 +MT18KSF1G72HZ-1G4E2,33,DDR3-SDRAM DEVICE TYPE,00 +MT18KSF1G72HZ-1G4E2,34,DDR3-FINE OFFSET FOR TCKMIN,00 +MT18KSF1G72HZ-1G4E2,35,DDR3-FINE OFFSET FOR TAAMIN,00 +MT18KSF1G72HZ-1G4E2,36,DDR3-FINE OFFSET FOR TRCDMIN,00 +MT18KSF1G72HZ-1G4E2,37,DDR3-FINE OFFSET FOR TRPMIN,00 +MT18KSF1G72HZ-1G4E2,38,DDR3-FINE OFFSET FOR TRCMIN,00 +MT18KSF1G72HZ-1G4E2,39,DDR3-BYTE 39 RESERVED,00 +MT18KSF1G72HZ-1G4E2,40,DDR3-BYTE 40 RESERVED,00 +MT18KSF1G72HZ-1G4E2,41,DDR3-PTRR TMAW MAC,84 +MT18KSF1G72HZ-1G4E2,42-59,DDR3-RESERVED BYTES 42-59,000000000000000000000000000000000000 +MT18KSF1G72HZ-1G4E2,60,DDR3-RC REV NOM MODULE HEIGHT,0F +MT18KSF1G72HZ-1G4E2,61,DDR3-MODULE THICKNESS (MAX),11 +MT18KSF1G72HZ-1G4E2,62,DDR3-REFERENCE RAW CARD ID,23 +MT18KSF1G72HZ-1G4E2,63,DDR3 - ADDRESS MAPPING/MODULE ATTRIBUTES,00 +MT18KSF1G72HZ-1G4E2,64,DDR3-HEATSPREADER SOLUTION,00 +MT18KSF1G72HZ-1G4E2,65,DDR3-REGISTER VENDOR ID (LSB),00 +MT18KSF1G72HZ-1G4E2,66,DDR3-REGISTER VENDOR ID (MSB),00 +MT18KSF1G72HZ-1G4E2,67,DDR3-REGISTER REVISON NUMBER,00 +MT18KSF1G72HZ-1G4E2,68,DDR3-REGISTER TYPE,00 +MT18KSF1G72HZ-1G4E2,69,DDR3-REG CTRL WORDS 1 AND ZERO,00 +MT18KSF1G72HZ-1G4E2,70,DDR3-REG CTRL WORDS 3 AND 2,00 +MT18KSF1G72HZ-1G4E2,71,DDR3-REG CTRL WORDS 5 AND 4,00 +MT18KSF1G72HZ-1G4E2,72,DDR3-REG CTRL WORDS 7 AND 6,00 +MT18KSF1G72HZ-1G4E2,73,DDR3-REG CTRL WORDS 9 AND 8,00 +MT18KSF1G72HZ-1G4E2,74,DDR3-REG CTRL WORDS 11 AND 10,00 +MT18KSF1G72HZ-1G4E2,75,DDR3-REG CTRL WORDS 13 AND 12,00 +MT18KSF1G72HZ-1G4E2,76,DDR3-REG CTRL WORDS 15 AND 14,00 +MT18KSF1G72HZ-1G4E2,77-116,DDR3-RESERVED BYTES 77-116,00000000000000000000000000000000000000000000000000000000000000000000000000000000 +MT18KSF1G72HZ-1G4E2,117,DDR3-MODULE MFR ID (LSB),80 +MT18KSF1G72HZ-1G4E2,118,DDR3-MODULE MFR ID (MSB),2C +MT18KSF1G72HZ-1G4E2,119,DDR3-MODULE MFR LOCATION ID,00 +MT18KSF1G72HZ-1G4E2,120,DDR3-MODULE MFR YEAR,00 +MT18KSF1G72HZ-1G4E2,121,DDR3-MODULE MFR WEEK,00 +MT18KSF1G72HZ-1G4E2,122-125,DDR3-MODULE SERIAL NUMBER,00000000 +MT18KSF1G72HZ-1G4E2,126-127,DDR3-CRC,FCB1 +MT18KSF1G72HZ-1G4E2,128-145,DDR3-MODULE PART NUMBER,18KSF1G72HZ-1G4E2 +MT18KSF1G72HZ-1G4E2,146,DDR3-MODULE DIE REV,45 +MT18KSF1G72HZ-1G4E2,147,DDR3-MODULE PCB REV,32 +MT18KSF1G72HZ-1G4E2,148,DDR3-DRAM DEVICE MFR ID (LSB),80 +MT18KSF1G72HZ-1G4E2,149,DDR3-DRAM DEVICE MFR (MSB),2C +MT18KSF1G72HZ-1G4E2,150-175,DDR3-MFR RESERVED BYTES 150-175,0000000000000000000000000000000000000000000000000000 +MT18KSF1G72HZ-1G4E2,176-255,DDR3-CUSTOMER RESERVED BYTES 176-255,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF \ No newline at end of file diff --git a/test/test_modules.py b/test/test_modules.py index e6a6fe7..2207e61 100644 --- a/test/test_modules.py +++ b/test/test_modules.py @@ -10,6 +10,11 @@ from litedram.modules import SDRAMModule, DDR3SPDData def load_spd_reference(filename): + """Load reference SPD data from a CSV file + + Micron reference SPD data can be obtained from: + https://www.micron.com/support/tools-and-utilities/serial-presence-detect + """ script_dir = os.path.dirname(os.path.realpath(__file__)) path = os.path.join(script_dir, "spd_data", filename) data = [0] * 256 @@ -18,7 +23,7 @@ def load_spd_reference(filename): for row in reader: address = row["Byte Number"] value = row["Byte Value"] - # ignore ranges (timings are specified per byte) + # Ignore ranges (data we care about is specified per byte anyway) if len(address.split("-")) == 1: data[int(address)] = int(value, 16) return data @@ -26,6 +31,7 @@ def load_spd_reference(filename): class TestSPD(unittest.TestCase): def test_tck_to_speedgrade(self): + # Verify that speedgrade transfer rates are calculated correctly from tck tck_to_speedgrade = { 2.5: 800, 1.875: 1066, @@ -64,31 +70,54 @@ class TestSPD(unittest.TestCase): self.assertEqual(txx, txx_ref) def test_MT16KTF1G64HZ(self): - data = load_spd_reference("MT16KTF1G64HZ-1G6N1.csv") kwargs = dict(clk_freq=125e6, rate="1:4") module_ref = litedram.modules.MT16KTF1G64HZ(**kwargs) - module = SDRAMModule.from_spd_data(data, **kwargs) - self.compare_geometry(module, module_ref) - sgt = module.speedgrade_timings["1600"] - self.assertEqual(sgt.tRP, 13.125) - self.assertEqual(sgt.tRCD, 13.125) - self.assertEqual(sgt.tRP + sgt.tRAS, 48.125) + + with self.subTest(speedgrade="-1G6"): + data = load_spd_reference("MT16KTF1G64HZ-1G6N1.csv") + module = SDRAMModule.from_spd_data(data, **kwargs) + self.compare_geometry(module, module_ref) + sgt = module.speedgrade_timings["1600"] + self.assertEqual(sgt.tRP, 13.125) + self.assertEqual(sgt.tRCD, 13.125) + self.assertEqual(sgt.tRP + sgt.tRAS, 48.125) + + with self.subTest(speedgrade="-1G9"): + data = load_spd_reference("MT16KTF1G64HZ-1G9E1.csv") + module = SDRAMModule.from_spd_data(data, **kwargs) + self.compare_geometry(module, module_ref) + sgt = module.speedgrade_timings["1866"] + self.assertEqual(sgt.tRP, 13.125) + self.assertEqual(sgt.tRCD, 13.125) + self.assertEqual(sgt.tRP + sgt.tRAS, 47.125) def test_MT18KSF1G72HZ(self): - data = load_spd_reference("MT18KSF1G72HZ-1G6E2.csv") kwargs = dict(clk_freq=125e6, rate="1:4") module_ref = litedram.modules.MT18KSF1G72HZ(**kwargs) - module = SDRAMModule.from_spd_data(data, **kwargs) - self.compare_geometry(module, module_ref) - sgt = module.speedgrade_timings["1600"] - self.assertEqual(sgt.tRP, 13.125) - self.assertEqual(sgt.tRCD, 13.125) - self.assertEqual(sgt.tRP + sgt.tRAS, 48.125) + + with self.subTest(speedgrade="-1G6"): + data = load_spd_reference("MT18KSF1G72HZ-1G6E2.csv") + module = SDRAMModule.from_spd_data(data, **kwargs) + self.compare_geometry(module, module_ref) + sgt = module.speedgrade_timings["1600"] + self.assertEqual(sgt.tRP, 13.125) + self.assertEqual(sgt.tRCD, 13.125) + self.assertEqual(sgt.tRP + sgt.tRAS, 48.125) + + with self.subTest(speedgrade="-1G4"): + data = load_spd_reference("MT18KSF1G72HZ-1G4E2.csv") + module = SDRAMModule.from_spd_data(data, **kwargs) + self.compare_geometry(module, module_ref) + sgt = module.speedgrade_timings["1333"] + self.assertEqual(sgt.tRP, 13.125) + self.assertEqual(sgt.tRCD, 13.125) + self.assertEqual(sgt.tRP + sgt.tRAS, 49.125) def test_MT8JTF12864(self): - data = load_spd_reference("MT8JTF12864AZ-1G4G1.csv") kwargs = dict(clk_freq=125e6, rate="1:4") module_ref = litedram.modules.MT8JTF12864(**kwargs) + + data = load_spd_reference("MT8JTF12864AZ-1G4G1.csv") module = SDRAMModule.from_spd_data(data, **kwargs) self.compare_geometry(module, module_ref) sgt = module.speedgrade_timings["1333"] @@ -97,12 +126,32 @@ class TestSPD(unittest.TestCase): self.assertEqual(sgt.tRP + sgt.tRAS, 49.125) def test_MT8KTF51264(self): - data = load_spd_reference("MT8KTF51264HZ-1G4E1.csv") kwargs = dict(clk_freq=100e6, rate="1:4") module_ref = litedram.modules.MT8KTF51264(**kwargs) - module = SDRAMModule.from_spd_data(data, **kwargs) - self.compare_geometry(module, module_ref) - sgt = module.speedgrade_timings["1333"] - self.assertEqual(sgt.tRP, 13.125) - self.assertEqual(sgt.tRCD, 13.125) - self.assertEqual(sgt.tRP + sgt.tRAS, 49.125) + + with self.subTest(speedgrade="-1G4"): + data = load_spd_reference("MT8KTF51264HZ-1G4E1.csv") + module = SDRAMModule.from_spd_data(data, **kwargs) + self.compare_geometry(module, module_ref) + sgt = module.speedgrade_timings["1333"] + self.assertEqual(sgt.tRP, 13.125) + self.assertEqual(sgt.tRCD, 13.125) + self.assertEqual(sgt.tRP + sgt.tRAS, 49.125) + + with self.subTest(speedgrade="-1G6"): + data = load_spd_reference("MT8KTF51264HZ-1G6E1.csv") + module = SDRAMModule.from_spd_data(data, **kwargs) + self.compare_geometry(module, module_ref) + sgt = module.speedgrade_timings["1600"] + self.assertEqual(sgt.tRP, 13.125) + self.assertEqual(sgt.tRCD, 13.125) + self.assertEqual(sgt.tRP + sgt.tRAS, 48.125) + + with self.subTest(speedgrade="-1G9"): + data = load_spd_reference("MT8KTF51264HZ-1G9P1.csv") + module = SDRAMModule.from_spd_data(data, **kwargs) + self.compare_geometry(module, module_ref) + sgt = module.speedgrade_timings["1866"] + self.assertEqual(sgt.tRP, 13.125) + self.assertEqual(sgt.tRCD, 13.125) + self.assertEqual(sgt.tRP + sgt.tRAS, 47.125)