1 // 2 // Copyright (c) 2010-2023 Antmicro 3 // 4 // This file is licensed under the MIT License. 5 // Full license text is available in 'licenses/MIT.txt'. 6 // 7 8 using Antmicro.Renode.Core; 9 using Antmicro.Renode.Core.Structure.Registers; 10 using Antmicro.Renode.Logging; 11 12 namespace Antmicro.Renode.Peripherals.Miscellaneous 13 { 14 public class LiteX_MMCM : BasicDoubleWordPeripheral, IKnownSize 15 { LiteX_MMCM(IMachine machine)16 public LiteX_MMCM(IMachine machine) : base(machine) 17 { 18 mmcmRegisters = new uint[RegistersCount]; 19 20 DefineRegisters(); 21 } 22 Reset()23 public override void Reset() 24 { 25 base.Reset(); 26 27 for(var i = 0; i < mmcmRegisters.Length; i++) 28 { 29 mmcmRegisters[i] = 0; 30 } 31 } 32 33 public long Size => 0x100; 34 DefineRegisters()35 private void DefineRegisters() 36 { 37 Registers.Reset.Define(this) 38 .WithFlag(0, FieldMode.WriteOneToClear, name: "reset", writeCallback: (_, val) => 39 { 40 if(val) 41 { 42 // this "reset" should not 43 // clear the internal mmcm registers 44 RegistersCollection.Reset(); 45 } 46 }) 47 .WithReservedBits(1, 7) 48 .WithIgnoredBits(8,24) 49 ; 50 51 Registers.Locked.Define(this) 52 .WithFlag(0, name: "locked", valueProviderCallback: _ => true) // we are always ready 53 .WithReservedBits(1, 7) 54 .WithIgnoredBits(8,24) 55 ; 56 57 Registers.Read.Define(this) 58 .WithFlag(0, FieldMode.WriteOneToClear, name: "read", writeCallback: (_, val) => 59 { 60 if(val) 61 { 62 HandleRead(); 63 } 64 }) 65 .WithReservedBits(1, 7) 66 .WithIgnoredBits(8,24) 67 ; 68 69 Registers.Write.Define(this) 70 .WithFlag(0, FieldMode.WriteOneToClear, name: "write", writeCallback: (_, val) => 71 { 72 if(val) 73 { 74 HandleWrite(); 75 } 76 }) 77 .WithReservedBits(1, 7) 78 .WithIgnoredBits(8,24) 79 ; 80 81 Registers.DataReady.Define(this) 82 .WithFlag(0, out dataReadyField, name: "drdy") 83 .WithReservedBits(1, 7) 84 .WithIgnoredBits(8,24) 85 ; 86 Registers.Address.Define(this) 87 .WithValueField(0, 8, out addressField, name: "addr") 88 .WithIgnoredBits(8,24) 89 ; 90 Registers.DataWriteLow.Define(this) 91 .WithValueField(0, 8, out dataWriteLowField, FieldMode.Write, name: "dat_wL") 92 .WithIgnoredBits(8,24) 93 ; 94 Registers.DataWriteHigh.Define(this) 95 .WithValueField(0, 8, out dataWriteHighField, FieldMode.Write, name: "dat_wH") 96 .WithIgnoredBits(8,24) 97 ; 98 Registers.DataReadLow.Define(this) 99 .WithValueField(0, 8, out dataReadLowField, FieldMode.Read, name: "dat_rL") 100 .WithIgnoredBits(8,24) 101 ; 102 Registers.DataReadHigh.Define(this) 103 .WithValueField(0, 8, out dataReadHighField, FieldMode.Read, name: "dat_rH") 104 .WithIgnoredBits(8,24) 105 ; 106 } 107 HandleRead()108 private void HandleRead() 109 { 110 if((int)addressField.Value >= mmcmRegisters.Length) 111 { 112 this.Log(LogLevel.Error, "Trying to read from a non-existing MMCM register #{0}. This model supports registers <0-{1}>", addressField.Value, mmcmRegisters.Length - 1); 113 return; 114 } 115 116 dataReadLowField.Value = (byte)mmcmRegisters[addressField.Value]; 117 dataReadHighField.Value = mmcmRegisters[addressField.Value] >> 8; 118 dataReadyField.Value = true; 119 } 120 HandleWrite()121 private void HandleWrite() 122 { 123 if((int)addressField.Value >= mmcmRegisters.Length) 124 { 125 this.Log(LogLevel.Error, "Trying to write to a non-existing MMCM register #{0}. This model supports registers <0-{1}>", addressField.Value, mmcmRegisters.Length - 1); 126 return; 127 } 128 129 mmcmRegisters[addressField.Value] = (uint)((dataWriteHighField.Value << 8) | dataWriteLowField.Value); 130 dataReadyField.Value = true; 131 } 132 133 private IFlagRegisterField dataReadyField; 134 private IValueRegisterField addressField; 135 private IValueRegisterField dataReadLowField; 136 private IValueRegisterField dataReadHighField; 137 private IValueRegisterField dataWriteLowField; 138 private IValueRegisterField dataWriteHighField; 139 140 private uint[] mmcmRegisters; 141 142 private const int RegistersCount = 0x50; // 0x4F is the last register in MMCM 143 144 private enum Registers 145 { 146 Reset = 0x0, 147 Locked = 0x4, 148 Read = 0x8, 149 Write = 0xc, 150 DataReady = 0x10, 151 Address = 0x14, 152 DataWriteLow = 0x18, 153 DataWriteHigh = 0x1c, 154 DataReadLow = 0x20, 155 DataReadHigh = 0x24 156 } 157 } 158 } 159