ezynq_ddr.py 119 KB
Newer Older
1
#!/usr/bin/env python
2
# -*- coding: utf-8 -*-
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
# Copyright (C) 2013, Elphel.inc.
# configuration of the DDR-related registers
# 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 2013, Elphel, Inc."
__license__ = "GPL"
__version__ = "3.0+"
__maintainer__ = "Andrey Filippov"
__email__ = "andrey@elphel.com"
__status__ = "Development"
25
import math
26 27
import ezynq_ddrc_defs
import ezynq_registers
28 29 30
import ezynq_ddrcfg_defs
import ezynq_feature_config
import ezynq_ddriob_def
31
import ezynq_slcr_clk_def
32 33 34 35 36 37 38 39
def set_random_bits(old,d,bits):
    data = 0
    mask = 0
    for i,b in enumerate(bits):
        mask  |= 1<< b
        data |= ((d>>i) & 1) << b
    return ((old ^ data) & mask) ^ old    
        
40
class EzynqDDR:
41 42 43 44 45
    def __init__(self,regs_masked,permit_undefined_bits=False,force=False,warn=False):
        self.DDRC_DEFS=  ezynq_ddrc_defs.DDRC_DEFS
        self.DDRIOB_DEFS=ezynq_ddriob_def.DDRIOB_DEFS
        self.DDR_CFG_DEFS=ezynq_ddrcfg_defs.DDR_CFG_DEFS
        self.features=ezynq_feature_config.EzynqFeatures(self.DDR_CFG_DEFS,0) #DDR_CFG_DEFS
46 47
        self.ddrc_register_set=  ezynq_registers.EzynqRegisters(self.DDRC_DEFS,0,regs_masked,permit_undefined_bits)
        self.ddriob_register_set=ezynq_registers.EzynqRegisters(self.DDRIOB_DEFS,0,regs_masked,permit_undefined_bits)
48

49 50 51 52 53 54 55 56
    
    def generate_command_queue_empty(self):
        # generate code to be included in u-boot for testing DDR command queue
        reg_set=  ezynq_registers.EzynqRegisters(ezynq_slcr_clk_def.SLCR_CLK_DEFS,0,[])
        reg_set.wait_reg_field_values('ddr_cmd_sta',  # DDR Command queue state
                                               (('cmd_q_empty',    0)), True) # 0 - no commands for DDRC are queued, 1 - commands pending
        return reg_set.get_register_sets(sort_addr=True,apply_new=True)
    
57
        
58 59 60 61
    def parse_parameters(self,raw_configs):
        self.features.parse_features(raw_configs)
    def check_missing_features(self):
        self.features.check_missing_features()
62 63 64 65 66 67 68 69 70 71 72
        if (self.features.get_par_value('SILICON')=='1'):
            self.silicon=1
        elif (self.features.get_par_value('SILICON')=='2'):
            self.silicon=2
        elif (self.features.get_par_value('SILICON')=='3'):
            self.silicon=3
        elif (self.features.get_par_value('SILICON')=='3.1'):
            self.silicon=3
        else:
            self.silicon=3    

73
    def html_list_features(self,html_file):
74 75
        if not html_file:
            return
76 77
        html_file.write('<h2>DDR memory configuration parameters</h2>\n')
        self.features.html_list_features(html_file)
78
    def calculate_dependent_pars(self,ddr_mhz):
79
#TODO: just testing on a few pars, migrate more of them
80 81 82
        if not self.features.is_known('FREQ_MHZ'):
            self.features.set_calculated_value('FREQ_MHZ',ddr_mhz,True)
            
83 84
        try:
            tCK=1000.0/self.features.get_par_value('FREQ_MHZ')
85 86
#            print 'FREQ_MHZ=',self.features.get_par_value('FREQ_MHZ')

87 88 89 90 91 92 93 94 95 96 97 98 99
            try:
                self.features.set_max_value('RP', int(math.ceil(self.features.get_par_value('T_RP')/tCK)))
            except:
                pass # get_par_value('T_RP') failed

            try:    
                self.features.set_max_value('RCD', int(math.ceil(self.features.get_par_value('T_RCD')/tCK)))
            except:
                pass
            try:
                self.features.set_max_value('RRD', int(math.ceil(self.features.get_par_value('T_RRD')/tCK)))
            except:
                pass
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117

            try:
                self.features.set_max_value('CKE', int(math.ceil(self.features.get_par_value('T_CKE')/tCK)))
            except:
                pass
            try:
                self.features.set_max_value('CKSRE', int(math.ceil(self.features.get_par_value('T_CKSRE')/tCK)))
            except:
                pass
            try:
                self.features.set_max_value('CKSRX', int(math.ceil(self.features.get_par_value('T_CKSRX')/tCK)))
            except:
                pass
            try:
                self.features.set_max_value('MOD', int(math.ceil(self.features.get_par_value('T_MOD')/tCK)))
            except:
                pass
        
118 119
        except:
            print "*** DDR Clock frequency is not defined"
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
    def pre_validate(self):
        if not self.features.get_par_value('ENABLE'):
            return
        is_LPDDR2=   (self.features.get_par_value('MEMORY_TYPE')=='LPDDR2')
        if (not is_LPDDR2) and (self.features.get_par_value('BL')>8):
            raise Exception("BL=16 is only supported in LPDDR2 memory")
    def post_validate(self):
        if not self.features.get_par_value('ENABLE'):
            return
        self._fix_address_map()

    def _fix_address_map(self):
        half_width= self.features.get_par_value('BUS_WIDTH') == 16
        ba_count=   self.features.get_par_value('BANK_ADDR_COUNT')
        ra_count=   self.features.get_par_value('ROW_ADDR_COUNT')
        ca_count=   self.features.get_par_value('COL_ADDR_COUNT')
        ba_map=     self.features.get_par_value('BANK_ADDR_MAP')
        try:
Andrey Filippov's avatar
Andrey Filippov committed
138
            _,_=self._map_ddr_addresses (ca_count,ra_count,ba_count,ba_map,half_width)
139 140 141 142 143 144 145
            return # all OK already
        except Exception, err:
            print "Specified value for the "+self.features.get_par_confname('BANK_ADDR_MAP')+'='+str(ba_map)+" is not valid:\n"+str(err)
        best_match=None
        for bm in range(3,30):
            if (best_match==None) or (abs(bm-ba_map) < abs(bm-ba_map)):
                try:
Andrey Filippov's avatar
Andrey Filippov committed
146
                    _,_=self._map_ddr_addresses (ca_count,ra_count,ba_count,bm,half_width)
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
                    best_match=bm
                except:
                    continue
        if best_match==None:
            raise Exception ('Could not find a suitable value for '+self.features.get_par_confname('BANK_ADDR_MAP'))            
        print "Replacing with: "+self.features.get_par_confname('BANK_ADDR_MAP')+'='+str(best_match)
        self.features.set_value('BANK_ADDR_MAP', best_match)
                        
        
                 
    def _map_ddr_addresses (self,num_ca,num_ra,num_ba,skip_ba,half_width):
        map_capabilities={
        #C/R/B, bit(s) (for CA - in full width mode), internal base - bit number, (valid:min,max) [,disable value]
            'col_b2':   ('C', 3, 2,( 0, 7)),
            'col_b3':   ('C', 4, 2,( 0, 7)),
            'col_b4':   ('C', 5, 2,( 0, 7)),
            'col_b5':   ('C', 6, 2,( 0, 7)),
            'col_b6':   ('C', 7, 2,( 0, 7)),
            'col_b7':   ('C', 8, 2,( 0, 7),0xf),
            'col_b8':   ('C', 9, 2,( 0, 7),0xf),
            'col_b9':   ('C',10, 2,( 0, 7),0xf),
            'col_b10':  ('C',11, 2,( 0, 7),0xf),
            'col_b11':  ('C',12, 2,( 0, 7),0xf),

            'row_b0':   ('R', 0, 9,( 0, 11)),
            'row_b1':   ('R', 1, 9,( 0, 11)),
            'row_b2_11':('R',( 2,11), 9,( 0, 11)),
            'row_b12':  ('R', 12, 9,( 0, 8),0xf),
            'row_b13':  ('R', 13, 9,( 0, 7),0xf),
            'row_b14':  ('R', 14, 9,( 0, 6),0xf),
            'row_b15':  ('R', 15, 9,( 0, 5),0xf),

            'bank_b0':('B', 0, 5,( 0, 14)),
            'bank_b1':('B', 1, 5,( 0, 14)),
            'bank_b2':('B', 2, 5,( 0, 14),0xf),
         }
        def map_field(name,bit):
            capability=map_capabilities[name]
            group=capability[0]
            add_base=capability[2]
            valid_limits=capability[3]
            try:
                disable=capability[4]
            except:
                disable=None
            if half_width and (group=='C'):
                bit += 1
            for i, map_bit in enumerate (map_axi):
                if (map_bit['TYPE']==group) and (map_bit['BIT']==bit):
                    extra=i-(bit+add_base)
                    if not extra in range(valid_limits[0],valid_limits[1]+1):
                        raise Exception ('Failed to map AXI_A['+str(i)+'] to '+group+'A ['+str(bit)+'], as the required value for '+
                                         name+'='+str(extra)+' is not in the valid range of '+str(valid_limits)+'.')
#                    print name, '->', extra    
                    return extra # this is the value of the bit field
            else: # This address bit of the group is not used - try to disable it
                if disable==None:
                    raise Exception ('Address bit '+group+'A ['+str(bit)+'], is not used, but it is not possible to disable it in the bit field '+name)
#                print name, '-> disable:', disable    
                return disable
207
            
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
        map_ba=skip_ba+(2,1)[half_width] # full AXI address to map BA0 to
        if (num_ba<2) or (num_ba>3):
            raise Exception('Wring number of bank addresses: '+str(num_ba)+", only 2 or 3 are supported")
        if (map_ba<5):
            raise Exception('Map bank address is too low, should be at least '+str(5-(2,1)[half_width]))
#        num_addresses=(2,1)[half_width]+num_ca+num_ra+num_ba
        map_axi=[{'TYPE':'NONE','BIT':0} for i in range((2,1)[half_width]+num_ca+num_ra+num_ba)]
        if map_ba > (len(map_axi)- num_ba):
            raise Exception('Map bank address is too high, should be not higher than '+str(len(map_axi)- num_ba))
        #Map AXI addresses to CA (logical, skipping A10 when applicable), RA, BA without restricting to hardware possibility
        map_left=skip_ba
        next_ca=0
        next_ra=0
        next_ba=0
        for i, map_bit in enumerate (map_axi):
            if i<(2,1)[half_width]:
                continue # did not get to the first address to map
            if (map_left==0) or (next_ba>0) and (next_ba<num_ba):
                map_bit['TYPE']='B'
                map_bit['BIT']=next_ba
                next_ba+=1
                map_left-=1 # so it will never trigger (map_left==0) again 
#                print 'i=',i,'type=',map_bit['TYPE'],'map_left=',map_left,'next_ca=',next_ca,'next_ra=',next_ra,'next_ba=',next_ba
                continue
            if (next_ca<num_ca):
                map_bit['TYPE']='C'
                map_bit['BIT']=next_ca
                next_ca+=1
            else:
                map_bit['TYPE']='R'
                map_bit['BIT']=next_ra
                next_ra+=1
            map_left-=1
#            print 'i=',i,'type=',map_bit['TYPE'],'map_left=',map_left,'next_ca=',next_ca,'next_ra=',next_ra,'next_ba=',next_ba
Andrey Filippov's avatar
Andrey Filippov committed
242 243 244 245 246 247
#        print map_axi
        #ug585:837 - details for ddrc.page_mask register
        page_mask=0
        for i, map_bit in enumerate (map_axi[3:]): # skip 3 LSB to get "This mask applies to 64-bit address and not byte address.". ***** TODO: Verify it is really 64 (8-byte), not 32 (4-byte) word address
            if map_bit['TYPE'] in 'BR': 
                page_mask |= 1<<i
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
        #now validate mapping, raise exception if invalid
        address_mapping={}
        for name in map_capabilities:
            capability=map_capabilities[name]
            bit=capability[1]
            if isinstance(bit,tuple):
                value=map_field(name,capability[1][0])
                for bit in range(capability[1][0]+1,capability[1][1]+1):
                    other=map_field (name,bit)
                    if other != value:
                        raise Exception ('It is not possible to independently assign mappings for '+capability[0]+'A['+str(capability[1][0])+
                                         ']='+str(value)+' and '+capability[0]+'A['+str(bit)+']='+str(other)+' as they are controlled by the same '+name+'.')
            else:
                value=map_field(name,capability[1])
            address_mapping[name]=value             
Andrey Filippov's avatar
Andrey Filippov committed
263
        return (address_mapping,page_mask)
264 265

    def get_new_register_sets(self):
266
        return self.ddrc_register_set.get_register_sets(True,True)
267 268 269

    def get_ddr_type(self):
        return self.features.get_par_value('MEMORY_TYPE')
270
    
271 272 273 274 275
    # Start DDR initialization procedure (unlock DDRC)
    def ddr_start(self,current_reg_sets,force=False,warn=False):
        ddrc_register_set=self.ddrc_register_set
        ddrc_register_set.set_initial_state(current_reg_sets, True)
        ddrc_register_set.set_bitfields('ddrc_ctrl',(('reg_ddrc_soft_rstb', 0x1)),force,warn)
276 277
        # add wait for DDR ready
        ddrc_register_set.wait_reg_field_values('mode_sts_reg',('ddrc_reg_operating_mode',0), False, warn)
278 279
        return ddrc_register_set.get_register_sets(True,True)
        
280
    def ddr_init_memory(self,current_reg_sets,force=False,warn=False):
281 282 283 284 285
#        print 'ddr_init_memory, len(current_reg_sets)=',len(current_reg_sets),'\n'
        if not self.features.get_par_value('ENABLE'):
            print 'DDR configuration is disabled'
            # do some stuff (write regs, output)
            return
286 287
        ddriob_register_set=self.ddriob_register_set
        ddrc_register_set=  self.ddrc_register_set
288
        ddriob_register_set.set_initial_state(current_reg_sets, True)# start from the current registers state
289
        
290
        self.ddr_init_ddriob(force,warn)
291 292
        regs1=ddriob_register_set.get_register_sets(True,True)
        ddrc_register_set.set_initial_state(regs1, True)# add
293
        self.ddr_init_ddrc(force,warn)
294 295
        return ddrc_register_set.get_register_sets(True,True)

296
    def ddr_init_ddrc(self,force=False,warn=False):
297
        ddrc_register_set=self.ddrc_register_set
298 299 300 301 302 303 304 305 306 307 308 309 310
        is_LPDDR2=   (self.features.get_par_value('MEMORY_TYPE')=='LPDDR2')
        is_DDR3L=    (self.features.get_par_value('MEMORY_TYPE')=='DDR3L')
        is_DDR3_15=  (self.features.get_par_value('MEMORY_TYPE')=='DDR3')
        is_DDR3=     is_DDR3_15 or is_DDR3L
        is_DDR2=     (self.features.get_par_value('MEMORY_TYPE')=='DDR2')
#       is_32=       (self.features.get_par_value('BUS_WIDTH') > 16)
#        is_int_vref=  self.features.get_par_value('INTERNAL_VREF')
        tCK=1000.0/self.features.get_par_value('FREQ_MHZ')
        tREFI=       1000*self.features.get_par_value('T_REFI_US')/(1,2)[self.features.get_par_value('HIGH_TEMP')] # ns
        tWR=         self.features.get_par_value('T_WR')
#lock ddr
        ddrc_register_set.set_word('ddrc_ctrl',0x80,force) # active low soft reset
#two rank, values  0x1081, 0x81081, 0x81081 (added reg_ddrc_wr_odt_block=1)
Andrey Filippov's avatar
Andrey Filippov committed
311 312 313 314 315
        tREFI_c32=   int(tREFI/tCK/32)
        use_rd_data_eye_level = (0,1)[self.features.get_par_value('TRAIN_DATA_EYE')] 
        use_rd_dqs_gate_level = (0,1)[self.features.get_par_value('TRAIN_READ_GATE')] 
        use_wr_level          = (0,1)[self.features.get_par_value('TRAIN_WRITE_LEVEL')] 
                      
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339
        ddrc_register_set.set_bitfields('two_rank_cfg',(('reg_ddrc_wr_odt_block',0),             # shown as 1/do not modify, but actual set value==0
                                                        ('reg_ddrc_addrmap_cs_bit0',0),
                                                        ('reg_ddrc_t_rfc_nom_x32',tREFI_c32),
                                                        ('reg_ddrc_active_ranks',1)),force,warn) # *** not documented 
#reg HPR, values 0x3c0780f - all 3 times, DEFAULT
        ddrc_register_set.set_bitfields('hpr_reg',(('reg_ddrc_hpr_xact_run_length',     0xf),
                                                   ('reg_ddrc_hpr_max_starve_x32',      0xf),
                                                   ('reg_ddrc_hpr_min_non_critical_x32',0xf)),force,warn) 
#reg LPR, values 0x2001001 - all 3 times, DEFAULT
        ddrc_register_set.set_bitfields('lpr_reg',(('reg_ddrc_lpr_xact_run_length',     0x8),
                                                   ('reg_ddrc_lpr_max_starve_x32',      0x2),
                                                   ('reg_ddrc_lpr_min_non_critical_x32',0x1)),force,warn) 
#reg WR_REG, values 0x14001 - all 3 times, DEFAULT
        ddrc_register_set.set_bitfields('wr_reg',(('reg_ddrc_w_max_starve_x32',      0x2), # opposite sequence from HPR,LPR
                                                  ('reg_ddrc_w_xact_run_length',     0x8),
                                                  ('reg_ddrc_w_min_non_critical_x32',0x1)),force,warn) 
#reg DRAM_param_reg0, values 0x4281a all 3 times
        tXSx1=512 # clock cycles
        tXSx32=tXSx1/32
        tRFCx1=int(math.ceil(self.features.get_par_value('T_RFC')/tCK))
        tRCx1= int(math.ceil(self.features.get_par_value('T_RC')/tCK))
        ddrc_register_set.set_bitfields('dram_param_reg0',(('reg_ddrc_post_selfref_gap_x32',tXSx32), # Default - OK, Micron tXSDLL=tDLLK=512 /32
                                                           ('reg_ddrc_t_rfc_min',           tRFCx1),
                                                           ('reg_ddrc_t_rc',                tRCx1)),force,warn)
340 341 342 343 344 345

        CKE=  self.features.get_par_value('CKE') # 4
        
        RAS_MIN= int(math.ceil(self.features.get_par_value('T_RAS_MIN')/tCK))
        RAS_MAX=9*tREFI # for Micron
        RAS_MAXx1024=int(RAS_MAX/tCK/1024)
346 347
        tFAWx1=int(math.ceil(self.features.get_par_value('T_FAW')/tCK))
        inactiveToPDx32=6 # cycles 'Power down after this many clocks of NOP/DESELECT (if enabled in mcr). Make configurable?
348
        WR=int(math.ceil(tWR/tCK))
349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365
#        print 'tWR=',tWR,'tCK=',tCK
        wr_options_ddr3=(16,5,6,7,8,10,12,14)
        # some values are not valid for DDR3 when writing to MR0 register, trying to fix WR (in tCK) to be valid
        if is_DDR3 and (not WR in wr_options_ddr3):
            print 'Calculated value for Write recovery (WR): '+str(WR)+ ' (as defined by tWR), is not valid for DDR3 MR0, it only supports '+str(sorted(wr_options_ddr3))
            print 'trying to adjust WR:'
            cheat_down=0.1 # reduce calculated WR if before rounding up it did not exceed integer value by more than 'cheat'
            WR1=int(math.ceil(tWR/tCK-cheat_down))
            if WR1 in wr_options_ddr3:
                print 'Using WR='+str(WR1)+' instead of '+str(WR)+' (cheating down), before rounding the value was '+str(tWR/tCK)
                WR=WR1
            elif (WR+1) in wr_options_ddr3:
                print 'Using WR='+str(WR+1)+' instead of '+str(WR)+' (to much to cheat down, increasing to next valid), before rounding the value was '+str(tWR/tCK)
                WR=WR+1
            else:
                raise Exception('Could not fix the value of WR, please check frequency ('+self.features.get_par_confname('FREQ_MHZ')+
                                ') and write recovery (ns) '+ self.features.get_par_confname('T_WR'))    
366 367
        WL=self.features.get_par_value('CWL')
        BL=self.features.get_par_value('BL')
368
        wr2pre=WL+BL/2+WR
369 370
        if is_LPDDR2:
            wr2pre+=1
371 372 373
        ddrc_register_set.set_bitfields('dram_param_reg1',(('reg_ddrc_t_cke',           CKE), # Default - OK, Micron tXSDLL=tDLLK=512 /32
                                                           ('reg_ddrc_t_ras_min',       RAS_MIN),
                                                           ('reg_ddrc_t_ras_max',       RAS_MAXx1024),
374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407
                                                           ('reg_ddrc_t_faw',           tFAWx1),
                                                           ('reg_ddrc_powerdown_to_x32',inactiveToPDx32),
                                                           ('reg_ddrc_wr2pre',          wr2pre)),force,warn)
# reg DRAM_param_reg2, 0x720238e5
        AL=       self.features.get_par_value('AL')
        tRCDx1=   max(self.features.get_par_value('RCD') - AL,1)
        tRTPx1=max(self.features.get_par_value('RTP'), int(math.ceil(self.features.get_par_value('T_RTP')/tCK))) # tRTPx1=   4 # good default
        if is_DDR2:
            RD2PRE=AL+BL/2+max(tRTPx1,2)-2
        elif is_DDR3:
            RD2PRE=AL+max(tRTPx1,4)    
        elif is_LPDDR2:
            RD2PRE=BL/2+tRTPx1-1    
        padPD=0 # ???
        XP=     self.features.get_par_value('XP') # 4
        tWTRx1=max(self.features.get_par_value('WTR'), int(math.ceil(self.features.get_par_value('T_WTR')/tCK))) # tWTRx1=   4 # good default
        if is_DDR2 or is_DDR3:
            WR2RD=WL+tWTRx1+BL/2
        elif is_LPDDR2:
            WR2RD=WL+tWTRx1+BL/2+1
        CL= self.features.get_par_value('CL')
        RL= CL+AL
        if is_DDR2 or is_DDR3:
            RD2WR=RL+BL/2+2-WL
        elif is_LPDDR2:
            RD2WR=RL+BL/2+int(math.ceil(self.features.get_par_value('T_DQSCK_MAX')/tCK))+1-WL
        
        if is_DDR2 or is_DDR3:
            write_latency=WL-1
        elif is_LPDDR2:
            write_latency=WL
        
        if is_LPDDR2:
            if WL<1:
Andrey Filippov's avatar
Andrey Filippov committed
408
                raise Exception('Minimal Write Latency supported for LPDDR2 is 1, while '+self.features.get_par_confname('CWL')+'='+str(WL))
409 410
        else:
            if WL<3:
Andrey Filippov's avatar
Andrey Filippov committed
411
                raise Exception('Minimal Write Latency supported for DDR2/DDR3 is 3, while '+self.features.get_par_confname('CWL')+'='+str(WL))
412 413 414 415 416
        ddrc_register_set.set_bitfields('dram_param_reg2',(('reg_ddrc_t_rcd',           tRCDx1), # 0x7
                                                           ('reg_ddrc_rd2pre',          RD2PRE), # 0x4
                                                           ('reg_ddrc_pad_pd',          padPD), # 0x0
                                                           ('reg_ddrc_t_xp',            XP), # 0x4
                                                           ('reg_ddrc_wr2rd',           WR2RD), # 0xe
417
#                                                           ('reg_ddrc_wr2rd',           WR2RD | 0x10), # TODO: REMOVE !!!!
418 419
                                                           ('reg_ddrc_rd2wr',           RD2WR), # 0x7 
                                                           ('reg_ddrc_write_latency',   write_latency)),force,warn) #5
420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435
# reg DRAM_param_reg3, 0x270872d0 , 0x272872d0, 0x272872d0 (first time reg_ddrc_sdram is not set, the rest is the same)
        enable_pad_powerdown=     True  # ?
        mode_ddr1_ddr2=           1
        en_dfi_dram_clk_disable = 0 # not clear - is it just enable for the action, or actually stopping the clock?
        ddrc_refresh_to_x32=      8 # start refresh after this inactivity (x32 cycles) if it is useful, but not yet required. Dynamic field
        RP=                       self.features.get_par_value('RP')
        refresh_margin=           2 # default, recommended not to be changed
        CCD=                      self.features.get_par_value('CCD')
        RRD=                      self.features.get_par_value('RRD')

        ddrc_register_set.set_bitfields('dram_param_reg3',(('reg_ddrc_loopback',               0), #0
                                                           ('reg_ddrc_dis_pad_pd',             (1,0)[enable_pad_powerdown]), #0
                                                           ('reg_phy_mode_ddr1_ddr2',          mode_ddr1_ddr2), #1
                                                           ('reg_ddrc_read_latency',           RL), #7
                                                           ('reg_ddrc_en_dfi_dram_clk_disable',en_dfi_dram_clk_disable), #0
                                                           ('reg_ddrc_mobile',                 (0,1)[is_LPDDR2]), # 0
436
                                                           ('reg_ddrc_sdram',                  (1,0)[self.silicon==3] ),  # Shown reserved/default==0, but actually is set to 1 (2 and 3-rd time)
437 438 439 440 441
                                                           ('reg_ddrc_refresh_to_x32',         ddrc_refresh_to_x32), # 8
                                                           ('reg_ddrc_t_rp',                   RP), # 7
                                                           ('reg_ddrc_refresh_margin',         refresh_margin), # 2
                                                           ('reg_ddrc_t_rrd',                  RRD), # 6
                                                           ('reg_ddrc_t_ccd',                  CCD-1)),force,warn) #4
442 443 444
# reg DRAM_param_reg4, 0, 0x3c, 0x3c
        ddrc_register_set.set_word     ('dram_param_reg4',0x0,force) # reset all fields. This register is controlled by the hardware during automatic initialization
        #Maybe just the LSBB (reg_ddrc_en_2t_timing_mode) is needed for "2t timing mode" - is it non-common? 
445
        ddrc_register_set.set_bitfields('dram_param_reg4',(('reg_ddrc_max_rank_rd',            (0xf,0)[self.silicon==3])),force,warn) # Not documented, but appears to be set in 2-nd and 3-rd round
446
        
447

448 449 450 451 452 453 454 455
        
# reg DRAM_init_param,  0x2007 always (default)
        MRD = self.features.get_par_value('CCD')
        pre_ocd_x32=0 # ... may be set to zero ...
        final_wait_x32=0x7 # leaving default - time to start scheduler after dram init init
        ddrc_register_set.set_bitfields('dram_init_param',(('reg_ddrc_t_mrd',                  MRD),         # 0x4
                                                           ('reg_ddrc_pre_ocd_x32',            pre_ocd_x32), # 0x0
                                                           ('reg_ddrc_final_wait_x32',         final_wait_x32)),force,warn) # 0x7
456 457
        
        
458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496
# reg DRAM_emr_reg,     0x8 always (default)
#        ddrc_register_set.set_word     ('dram_emr_reg',        0x8, force)
        emr3=0 # Only 3 LSBs are used by DDR and should be set to 0 - correct values will be set by  the DDRC
        if is_LPDDR2:
            #use MR3 for the emr2. Lower 3 bits encode impedance, for now just using default value of
            emr2=2 # 40 Ohm
        else: #DDR2, DDR3
            emr2_00_02=0
            emr2_03_05=WL-5
            if emr2_03_05 < 0:
                emr2_03_05=0
            emr2_03_05 &= 0x7
            emr2_06_06= 0 # Auto Self Refresh - 0 manual, 1 - auto
            emr2_07_07= (0,1)[self.features.get_par_value('HIGH_TEMP')] # 
            emr2_08_08= 0
            emr2_09_10= 0 # Dynamic ODT control
            emr2_11_15= 0
            emr2=((emr2_00_02 <<  0) |
                  (emr2_03_05 <<  3) |
                  (emr2_06_06 <<  6) |
                  (emr2_07_07 <<  7) |
                  (emr2_08_08 <<  8) |
                  (emr2_09_10 <<  9) |
                  (emr2_11_15 << 11))
        ddrc_register_set.set_bitfields('dram_emr_reg',   (('reg_ddrc_emr3',                   emr3), # 0
                                                           ('reg_ddrc_emr2',                   emr2)),force,warn) # 0x8
# reg DRAM_emr_mr_reg,  0x40930 always (default)
#calculate mr value for different memory types            
        emr=0
        if is_DDR3 : # MR1
            emr_disableDLL=0     #  Disable DLL
            emr_driveStrength=0  #  0 - 40 OHm, 1 - 34 Ohm, 2,3 - reserved
            if AL==0:
                emr_AL=0
            elif AL==(CL-1):
                emr_AL=1     
            elif AL==(CL-2):
                emr_AL=2     
            else:
Andrey Filippov's avatar
Andrey Filippov committed
497
                raise Exception ('Wrong value for additive latency ('+self.features.get_par_confname('AL')+': '+str(AL)+', only 0, CL-1, CL-2 are supported in DDR3 memory. CL is '+str(CL))
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521
            emr_RTT=0
            if self.features.get_par_value('DDR3_RTT')[:2]=='60':
                emr_RTT=1
            elif self.features.get_par_value('DDR3_RTT')[:2]=='12':
                emr_RTT=2
            elif self.features.get_par_value('DDR3_RTT')[:2]=='40':
                emr_RTT=3

            emr_WL=   0       # 0 - disabled (normal), 1 - write leveling (will be set by DDRC, set to 0 here)
            emr_TDQS= 0 # Termination data strobe - only applicable to x8 memory
            emr_Qoff= 0 # 1 - tristate all DQ and DQS outputs
            #According to description of the MR1 bits:
            emr=set_random_bits(emr,  emr_disableDLL,    (0,))
            emr=set_random_bits(emr,  emr_driveStrength, (1,5))
            emr=set_random_bits(emr,  emr_AL,            (3,4))
            emr=set_random_bits(emr,  emr_RTT,           (2,6,9))
            emr=set_random_bits(emr,  emr_WL,            (7,))
            emr=set_random_bits(emr,  emr_TDQS,          (11,))
            emr=set_random_bits(emr,  emr_Qoff,          (12,))
        elif is_DDR2: # EMR
            emr_disableDLL=   0  #  Disable DLL
            emr_driveStrength=0  #  0 -full, 1 - reduced
            emr_AL=AL
            if (AL<0) or (AL>6):
Andrey Filippov's avatar
Andrey Filippov committed
522
                raise Exception ('Wrong value for additive latency ('+self.features.get_par_confname('AL')+': '+str(AL)+', only 0...6 are supported in DDR2 memory')
523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564
            emr_RTT=0
            if self.features.get_par_value('DDR2_RTT')[:2]=='75':
                emr_RTT=1
            elif self.features.get_par_value('DDR2_RTT')[:2]=='15':
                emr_RTT=2
            elif self.features.get_par_value('DDR2_RTT')[:2]=='50':
                emr_RTT=3
            emr_OCD_oper=   0 # these bits are ignored for DDR2
            emr_DQS_disable=0
            emr_RDQS=       0
            emr_DQ_disable= 0
            emr=set_random_bits(emr,  emr_disableDLL,    (0,))
            emr=set_random_bits(emr,  emr_driveStrength, (1,))
            emr=set_random_bits(emr,  emr_AL,            (3,4,5))
            emr=set_random_bits(emr,  emr_RTT,           (2,6))
            emr=set_random_bits(emr,  emr_OCD_oper,      (7,8,9))
            emr=set_random_bits(emr,  emr_DQS_disable,   (10,))
            emr=set_random_bits(emr,  emr_RDQS,          (11,))
            emr=set_random_bits(emr,  emr_DQ_disable,    (12,))
        elif is_LPDDR2: # MR2
            rlwl_options=((3,1),(4,2),(5,2),(6,3),(7,4),(8,4))
            rlwl=(RL,WL)
            try:
                mr2_rlwl=((3,1),(4,2),(5,2),(6,3)).index(rlwl)+1
            except:
                raise Exception('Wrong RL/WL combination: '+str(rlwl)+', LPDDR2 only supports '+str(rlwl_options))    
            emr=mr2_rlwl
#calculate mr value for different memory types            
        mr=0
        if is_DDR3 : #MR0
            if BL==4:
                mr_bl=2
            elif BL==8:        
                mr_bl=0
            else:
                raise Exception('Wrong burst length for DDR3: '+str(BL)+' - only 4 and 8 are supported')
            mr_bt=0 # 0 - sequential, 1 - interleaved - is it supported?
            try:  
                mr_cl=(2,4,6,8,10,12,14,1,3,5)[CL-5]
            except:
                raise Exception('Wrong value for CAS latency: '+str(CL)+ ' - only CL=5..14 are supported by DDR3')
            mr_dll_reset=1 # Seems to be always set (including dflt)?
565
            wr_options_ddr3=(16,5,6,7,8,10,12,14)
566
            try:
567
                mr_write_recovery=wr_options_ddr3.index(WR)
568
            except:
569
                raise Exception('Wrong value for Write recovery (WR): '+str(WR)+ ' (may be defined by tWR), DDR3 only supports '+str(sorted(wr_options_ddr3)))
570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630
            mr_PD = 0 # 0 - DLL off during PD (slow exit), 1 - DLL on during PD (fast exit)            
            mr=set_random_bits(mr,  mr_bl,            (0,1))
            mr=set_random_bits(mr,  mr_bt,            (3, ))
            mr=set_random_bits(mr,  mr_cl,            (2,4,5,6))
            mr=set_random_bits(mr,  mr_dll_reset,     (8,))
            mr=set_random_bits(mr,  mr_write_recovery,(9,10,11))
            mr=set_random_bits(mr,  mr_PD,            (12,))
        elif is_DDR2: # MR
            if BL==4:
                mr_bl=2
            elif BL==8:        
                mr_bl=3
            else:
                raise Exception('Wrong burst length for DDR2: '+str(BL)+' - only 4 and 8 are supported')
            mr_bt=0 # 0 - sequential, 1 - interleaved - is it supported?
            try:  
                mr_cl=(3,4,5,6,7)[CL-3]
            except:
                raise Exception('Wrong value for CAS latency '+str(CL)+ ' - only CL=3..7 are supported')
            mr_tm=0 # 0 - normal, 1 - test
            mr_dll_reset=1 # Always reset for DDR3, doing the same for DDR2 
            wr_options=(2,3,4,5,6,7,8)
            try:
                mr_write_recovery=wr_options.index(WR)+1
            except:
                raise Exception('Wrong value for Write recovery (WR) (may be defined by tWR) '+str(WR)+ ', DDR2 only supports '+str(wr_options))
            mr_PD = 0 # 0 - fast exit (normal), 1 - slow exit (low power)            
            
            mr=set_random_bits(mr,  mr_bl,            (0,1,2))
            mr=set_random_bits(mr,  mr_bt,            (3, ))
            mr=set_random_bits(mr,  mr_cl,            (4,5,6))
            mr=set_random_bits(mr,  mr_tm,            (7,))
            mr=set_random_bits(mr,  mr_dll_reset,     (8,))
            mr=set_random_bits(mr,  mr_write_recovery,(9,10,11))
            mr=set_random_bits(mr,  mr_PD,            (12,))

        elif is_LPDDR2: # MR1
            bl_options=(4,8,16)
            try:
                mr_bl=bl_options.index(BL)
            except:
                raise Exception('Wrong burst length '+str(BL)+' - LPDDR2 only supports '+str(bl_options))
            mr_bt=0 # 0 - sequential, 1 - interleaved - is it supported?
            mr_wrap=0 # 0 - wrap(default), 1 - no wrap
            wr_options=(3,4,5,6,7,8)
            try:
                mr_write_recovery=wr_options.index(WR)+1
            except:
                raise Exception('Wrong value for Write recovery (WR) (may be defined by tWR) '+str(WR)+ ', LPDDR2 only supports '+str(wr_options))
            mr=set_random_bits(mr,  mr_bl,            (0,1,2))
            mr=set_random_bits(mr,  mr_bt,            (3, ))
            mr=set_random_bits(mr,  mr_wrap,          (4, ))
            mr=set_random_bits(mr,  mr_write_recovery,(5,6,7))

#        ddrc_register_set.set_word     ('dram_emr_mr_reg', 0x40930, force)
        ddrc_register_set.set_bitfields('dram_emr_mr_reg',(('reg_ddrc_emr',                    emr), # 0x4
                                                           ('reg_ddrc_mr',                     mr)),force,warn) # 0x930
# reg DRAM_burst8_rdwr, 0x10694 always (default=0x20304)
#
        if   is_DDR3:
            t_post_cke=400.0
631 632 633 634 635
#            t_pre_cke= 200000.0
            t_pre_cke= 500000.0 # as generated by Vivado 2013.3, maybe same applies to other DDRx
#TODO: REMOVE !!!!            
#            t_pre_cke= 200000.0 # as generated by Vivado 2013.3, maybe same applies to other DDRx
            
636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673
        elif is_DDR2:
            t_post_cke=400.0
            t_pre_cke= 200000.0
        elif is_LPDDR2:
            t_post_cke=200000.0
            t_pre_cke= 20000000.0 # UG585.790 specifies :LPDDR2 - tINIT0 of 20 mS (max) + tINIT1 of 100nS (min), and 20mS > 10 bits
        post_cke_x1024= int(math.ceil(t_post_cke/tCK/1024))
        pre_cke_x1024=  int(math.ceil(t_pre_cke/tCK/1024))
        if (pre_cke_x1024)>1023:
            pre_cke_x1024=1023 # maximal value
        if BL==4:
            burst_rdwr=2
        elif BL==8:      
            burst_rdwr=4
        elif BL==16: # LPDDR2 only      
            burst_rdwr=8
#        ddrc_register_set.set_word     ('dram_burst8_rdwr',0x10694, force)
        ddrc_register_set.set_bitfields('dram_burst8_rdwr',(('reg_ddrc_burstchop',             0), #  0
                                                            ('reg_ddrc_post_cke_x1024',        post_cke_x1024), #  0x1
                                                            ('reg_ddrc_pre_cke_x1024',         pre_cke_x1024), #  0x69
                                                            ('reg_ddrc_burst_rdwr',            burst_rdwr)),force,warn) # 0x4
# reg DRAM_disable_dq,  0 always (default)
#        ddrc_register_set.set_word     ('dram_disable_dq',     0x0, force)
        ddrc_register_set.set_bitfields('dram_disable_dq',(('reg_phy_dq0_wait_t',              0), # 0
                                                           ('reg_phy_rd_level_start',          0), # 0
                                                           ('reg_phy_wr_level_start',          0), # 0
                                                           ('reg_phy_debug_mode',              0), # 0
                                                           ('reg_ddrc_dis_dq',                 0), # 0
                                                           ('reg_ddrc_force_low_pri_n',        0)),force,warn) # 0
        
# Using some of the the possible address mappings, defined by a single parameter BANK_ADDR_MAP:
# First CA and RA are considered continuous (skipping CA[10] when applicable), then all bank address bits are inserted,
# leaving BANK_ADDR_MAP bits (some CA, all CA or ALL CA and some RA ) lower          
        half_width= self.features.get_par_value('BUS_WIDTH') == 16
        ba_count=   self.features.get_par_value('BANK_ADDR_COUNT')
        ra_count=   self.features.get_par_value('ROW_ADDR_COUNT')
        ca_count=   self.features.get_par_value('COL_ADDR_COUNT')
        ba_map=     self.features.get_par_value('BANK_ADDR_MAP')
Andrey Filippov's avatar
Andrey Filippov committed
674 675 676
        addr_map,page_addr_mask =self._map_ddr_addresses (ca_count,ra_count,ba_count,ba_map,half_width)
        if not self.features.get_par_value('ARB_PAGE_BANK'):
            page_addr_mask=0 #default
677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702
        
# reg DRAM_addr_map_bank,  0x777 always (default)
        ddrc_register_set.set_bitfields('dram_addr_map_bank',(('reg_ddrc_addrmap_col_b6',   addr_map['col_b6']),             # 0
                                                              ('reg_ddrc_addrmap_col_b5',   addr_map['col_b5']),             # 0
                                                              ('reg_ddrc_addrmap_bank_b2',  addr_map['bank_b2']),            # 0x7
                                                              ('reg_ddrc_addrmap_bank_b1',  addr_map['bank_b1']),            # 0x7
                                                              ('reg_ddrc_addrmap_bank_b0',  addr_map['bank_b0'])),force,warn)# 0x7

# reg DRAM_addr_map_col,   0xfff00000 always (default)
        ddrc_register_set.set_bitfields('dram_addr_map_col', (('reg_ddrc_addrmap_col_b11',  addr_map['col_b11']),            # 0xf
                                                              ('reg_ddrc_addrmap_col_b10',  addr_map['col_b10']),            # 0xf
                                                              ('reg_ddrc_addrmap_col_b9',   addr_map['col_b9']),             # 0xf
                                                              ('reg_ddrc_addrmap_col_b8',   addr_map['col_b8']),             # 0
                                                              ('reg_ddrc_addrmap_col_b7',   addr_map['col_b7']),             # 0
                                                              ('reg_ddrc_addrmap_col_b4',   addr_map['col_b4']),             # 0
                                                              ('reg_ddrc_addrmap_col_b3',   addr_map['col_b3']),             # 0
                                                              ('reg_ddrc_addrmap_col_b2',   addr_map['col_b2'])),force,warn) # 0

# reg DRAM_addr_map_row,   0xf666666 always (default)
        ddrc_register_set.set_bitfields('dram_addr_map_row', (('reg_ddrc_addrmap_row_b15',  addr_map['row_b15']),            # 0xf
                                                              ('reg_ddrc_addrmap_row_b14',  addr_map['row_b14']),            # 0x6
                                                              ('reg_ddrc_addrmap_row_b13',  addr_map['row_b13']),            # 0x6
                                                              ('reg_ddrc_addrmap_row_b12',  addr_map['row_b12']),            # 0x6
                                                              ('reg_ddrc_addrmap_row_b2_11',addr_map['row_b2_11']),          # 0x6
                                                              ('reg_ddrc_addrmap_row_b1',   addr_map['row_b1']),             # 0x6
                                                              ('reg_ddrc_addrmap_row_b0',   addr_map['row_b0'])),force,warn) # 0x6
703 704 705 706
        

# reg DRAM_odt_reg,  0x3c000, 0x3c248,0x3c248
# Could not find documentation, default value may work (first time 3 default/do not change values were different
707 708 709
        rank0_wr_odt = (1,0)[self.silicon==3]  # default, was 0 first time
        rank1_rd_odt = (1,0)[self.silicon==3]  # default, was 0 first time
        rank1_wr_odt = (1,0)[self.silicon==3]  # default, was 0 first time
710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748
        wr_local_odt = 3  # default
        idle_local_odt= 3 # default
         
        ddrc_register_set.set_bitfields('dram_odt_reg', (
                                                      #  ('reg_ddrc_rank3_wr_odt',  0),              # 0
                                                      #  ('reg_ddrc_rank3_rd_odt',  0),              # 0
                                                      #  ('reg_ddrc_rank2_wr_odt',  0),              # 0
                                                      #  ('reg_ddrc_rank2_rd_odt',  0),              # 0 
                                                         ('reg_phy_idle_local_odt', idle_local_odt), # 0x3 0x3
                                                         ('reg_phy_wr_local_odt',   wr_local_odt),   # 0x3 0x3
                                                      #  ('reg_phy_rd_local_odt',   0),              # 0
                                                         ('reg_ddrc_rank1_wr_odt',  rank1_wr_odt),   # 0   0x1
                                                         ('reg_ddrc_rank1_rd_odt',  rank1_rd_odt),   # 0   0x1
                                                         ('reg_ddrc_rank0_wr_odt',  rank0_wr_odt),   # 0   0x1
                                                         ('reg_ddrc_rank0_rd_odt',  0)),force,warn)  # 0
        

        
# reg phy_cmd_timeout_rddata_cpt,  0x77010800 (default) all 3 times
        wrlvl_num_of_dq0   = 7 # write. lev. :recomm. 8 - higher longer, but better
        gatelvl_num_of_dq0 = 7 # gate training :recomm. 8 - higher longer, but better
        use_fixed_re       = 1 # FIFO control mode. Should be set to 1 during training/leveling
        rdc_we_to_re_delay = 8 # Fifo control, used when use_fixed_re=1 
        ddrc_register_set.set_bitfields('phy_cmd_timeout_rddata_cpt',(
                                                         ('reg_phy_wrlvl_num_of_dq0',        wrlvl_num_of_dq0),  # 0x7
                                                         ('reg_phy_gatelvl_num_of_dq0',      gatelvl_num_of_dq0),# 0x7
                                                      #  ('reserved1',                       0),                 # 0
                                                      #  ('reg_phy_clk_stall_level',         0),                 # 0
                                                      #  ('reg_phy_dis_phy_ctrl_rstn',       0),                 # 0
                                                      #  ('reg_phy_rdc_fifo_rst_err_cnt_clr',0),                 # 0
                                                         ('reg_phy_use_fixed_re',            use_fixed_re),      # 0x1
                                                      #  ('reg_phy_rdc_fifo_rst_disable',    0),                 # 0
                                                      #  ('reserved2',                       0),                 # 0
                                                         ('reg_phy_rdc_we_to_re_delay',      rdc_we_to_re_delay),# 0x8
                                                      #  ('reg_phy_wr_cmd_to_data',          0),                 # 0
                                                      #  ('reg_phy_rd_cmd_to_data',          0)                  # 0
                                                                                               ),force,warn)
# reg DLL_calib,  0x0, then 2 times 0x101 (default). Does it need to be 0 before training. Not listed in 10-11 - probably can be skipped during init
        dis_dll_calib = 0 # if 1 - disable automatic periodic DLL correction
749 750
        dll_calib_to_max_x1024 = (1,0)[self.silicon==3] # reserved, do not modify
        dll_calib_to_min_x1024 = (1,0)[self.silicon==3] # reserved, do not modify
751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794
        ddrc_register_set.set_bitfields('dll_calib',(('reg_ddrc_dis_dll_calib',             dis_dll_calib),          # 0
                                                     ('reg_ddrc_dll_calib_to_max_x1024',    dll_calib_to_max_x1024), # 1
                                                     ('reg_ddrc_dll_calib_to_min_x1024',    dll_calib_to_min_x1024)  # 1
                                                                                             ),force,warn)
# reg odt_delay_hold,  0x5003 (default) always
        if BL==4:
            wr_odt_hold= 2 # recommended ug585:801
        elif BL==8:   
            wr_odt_hold= 4 # recommended ug585:801
        else: #BL==16?
            wr_odt_hold= 8 # guessed
        wr_odt_hold+=1     # actually for BL==8 was programmed 5, so increment by 1. Or is it for 8 only?
        if is_DDR2:    
            wr_odt_delay=WL-5
            if wr_odt_delay<0:
                wr_odt_delay=0
        else:
            wr_odt_delay=0
        ddrc_register_set.set_bitfields('odt_delay_hold',(
                                                     ('reg_ddrc_wr_odt_hold',          wr_odt_hold),       # 5
                                                #    ('reg_ddrc_rd_odt_hold',          0),                 # 0 - 'unused'
                                                     ('reg_ddrc_wr_odt_delay',         wr_odt_delay),      # 0
                                                #    ('reg_ddrc_rd_odt_delay',         0),                 # 3 - 'unused' - keep default
                                                                                             ),force,warn)
# reg  ctrl_reg1 - all 3 times 0x3e (default) 
        ddrc_register_set.set_bitfields('ctrl_reg1',(
                                                     ('reg_ddrc_selfref_en',            0),       # 0 Dynamic - 1 - go to Self Refresh when transaction store is empty  
                                                     ('reserved1',                      0),       # 0
                                                     ('reg_ddrc_dis_collision_page_opt',0),       # 0 Disable autoprecharge for collisions (write+write or read+write to the same address) when  reg_ddrc_dis_wc==1
                                                     ('reg_ddrc_dis_wc',                0),       # 0 1 - disable write combine, 0 - enable
                                                     ('reg_ddrc_refresh_update_level',  0),       # 0 Dynamic: toggle to indicate refresh register(s) update
                                                     ('reg_ddrc_auto_pre_en',           0),       # 0 1 - most R/W will be with autoprecharge
                                                     ('reg_ddrc_lpr_num_entries',       0x1f),    # 0x1f - (bit 6 ignored) (Size of low priority transaction store+1). HPR - 32 - this value
                                                     ('reg_ddrc_pageclose',             0)        # 0 1 - close bank if no transactions in the store for it, 0 - keep open until not needed by other
                                                                                          ),force,warn)
# reg  ctrl_reg2 0x20000 - all 3 times (default)
        ddrc_register_set.set_bitfields('ctrl_reg2',(
                                                     ('reg_arb_go2critical_en',         0x1),     # 0x1 0 - ignore "urgent" from AXI master, 1 - grant
                                                     ('reserved1',                      0),       # 0 
                                                     ('reg_ddrc_go2critical_hysteresis',0),       # 0 Latency of moving to critical state
                                                     ('reserved2',                      0),       # 0
                                                                                          ),force,warn)
# reg  ctrl_reg3 0x284141 - all 3 times (non-default, default=0x00284027)
        if is_DDR3: # other - N/A
795
            dfi_t_wlmrd= self.features.get_par_value('WLMRD')
796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885
            rdlvl_rr  = 0x41 # default = 0x40 (Did not understand how to calculate, using actual for DDR3) 
            ddrc_register_set.set_bitfields('ctrl_reg3',(('reg_ddrc_dfi_t_wlmrd', dfi_t_wlmrd),
                                                         ('reg_ddrc_rdlvl_rr',    rdlvl_rr)),force,warn)   # 0x28 DDR3 only: tWLMRD from DRAM specs
        if is_DDR3 or is_LPDDR2: # DDR2 - N/A
            wrlvl_ww=RL+rdc_we_to_re_delay+50 #ug585:804
            ddrc_register_set.set_bitfields('ctrl_reg3',(('reg_ddrc_wrlvl_ww', wrlvl_ww)),force,warn)   # 0x41 (dflt 0x27) DDR3 and LPDDR2 - write  leveling write-to-write delay'
        
# reg  ctrl_reg4 0x1610 - all 3 times (default) - keeping
        ddrc_register_set.set_bitfields('ctrl_reg4',(
                                                     ('dfi_t_ctrlupd_interval_max_x1024',            0x16),       # 0x16 - maximal time between DFI update requests in 1024 clocks
                                                     ('dfi_t_ctrlupd_interval_min_x1024',            0x10),       # 0x10 - minimal time between DFI update requests in 1024 clocks
                                                                                          ),force,warn)
#     'rd_dll_force1':           {'OFFS': 0x070},
#     'wr_ratio_reg':            {'OFFS': 0x074},

# reg  ctrl_reg5 0x466111 - only 2 times set, but same default
        #CKE=  self.features.get_par_value('CKE') # 4 defined earlier
        CKSRE=  self.features.get_par_value('CKSRE') # 6
        CKSRX=  self.features.get_par_value('CKSRX') # 6
        if is_DDR3:
            t_ckesr=CKE+1 # contradicts dram_param_reg1 in actual settings - both have 0x4, but one - CKE, another CKE+1. Better safe than sorry, and SR exit is not that often
            t_cksrx=CKSRX
            t_cksre=CKSRE
        elif is_DDR2:
            t_ckesr=CKE
            t_cksrx=1
            t_cksre=1
        elif is_LPDDR2:
            t_ckesr=CKSRX
            t_cksrx=2
            t_cksre=2
        dfi_t_dram_clk_enable=1 # keeping defaults==actual for DDR3 - not clear what specs to use 
        dfi_t_dram_clk_disable=1 # keeping defaults==actual for DDR3 - not clear what specs to use
        dfi_t_ctrl_delay=1 # keeping defaults==actual for DDR3 - not clear what specs to use
        ddrc_register_set.set_bitfields('ctrl_reg5',(
                                                     ('reserved1',                       0  ),       # 0
                                                     ('reg_ddrc_t_ckesr',                t_ckesr),       # 0x4->5 Min CKE low for self refresh, recomm.: DDR3:tCKE+1,DDR2:tCKE,LPDDR2:tCKESR
                                                     ('reg_ddrc_t_cksrx',                t_cksrx),       # 0x6 CK valid before self refresh exit, recomm. DDR3:tCKSRX,DDR2:1,LPDDR2:2
                                                     ('reg_ddrc_t_cksre',                t_cksre),       # 0x6 CK valid after self refresh entry, recomm. DDR3:tCKSRE,DDR2:1,LPDDR2:2
                                                     ('reg_ddrc_dfi_t_dram_clk_enable',  dfi_t_dram_clk_enable),       # 0x1 deassert dfi_dram_clock disable to PHY clock enable in DFI clock cycles
                                                     ('reg_ddrc_dfi_t_dram_clk_disable', dfi_t_dram_clk_disable),       # 0x1 assert  dfi_dram_clock disable to PHY clock disable in DFI clock cycles
                                                     ('reg_ddrc_dfi_t_ctrl_delay',       dfi_t_ctrl_delay),       # 0x1 ssert/deassert  DFI control signals to PHY-DRAM control signals
                                                                                          ),force,warn)

# reg  ctrl_reg6 0x32222 - only 2 times set, but same default
# Keeping actual/defaults - all recommendations are listed for LPDDR2 only (tXP+2 for DDR3 would be 6 - does not match actual).
        ddrc_register_set.set_bitfields('ctrl_reg6',(
                                                     ('reserved1',            0),         # 0
                                                     ('reg_ddrc_t_ckcsx',     0x3),       # 0x3 Clock stable before exiting clock stop. Recommended for LPDDR2: tXP+2
                                                     ('reg_ddrc_t_ckdpdx',    0x2),       # 0x2 Clock stable before Deep Power Down exit. Recommended for LPDDR2: 2
                                                     ('reg_ddrc_t_ckdpde',    0x2),       # 0x2 Maintain clock after Deep Power Down entry. Recommended for LPDDR2: 2
                                                     ('reg_ddrc_t_ckpdx',     0x2),       # 0x2 Clock stable before Power Down exit. Recommended for LPDDR2: 2
                                                     ('reg_ddrc_t_ckpde',     0x2),       # 0x2 Maintain clock after Power Down entry. Recommended for LPDDR2: 2
                                                                                          ),force,warn)
# reg  che_refresh_timer01_reg dflt=0x00008000 = act 
        ddrc_register_set.set_bitfields('che_refresh_timer01_reg',(
                                                     ('refresh_timer1_start_value_x32',  0x8),# 0x8 reserved, do not modify
                                                     ('refresh_timer0_start_value_x32',  0),  # 0   reserved, do not modify
                                                                                          ),force,warn)

# reg  che_t_zq  dflt=0x10300802 act=0x10200802
        ZQCS=self.features.get_par_value('ZQCS')
        ZQCL=self.features.get_par_value('ZQCL')
        MOD= self.features.get_par_value('MOD')
        t_mod=max(MOD,512) # 128) # according to documentation should be 128, but actually it is set to 0x200
        dis_auto_zq=0 # default 0 - enable auto ZQ
        ddrc_register_set.set_bitfields('che_t_zq',(
                                                     ('reg_ddrc_t_zq_short_nop',  ZQCS), # 0x40 DDR3 and LPDDR2 only: number of NOP after ZQCS (ZQ calibration short)
                                                     ('reg_ddrc_t_zq_long_nop',   ZQCL), # 0x200 DDR3 and LPDDR2 only: number of NOP after ZQCL (ZQ calibration long)
                                                     ('reg_ddrc_t_mod',           t_mod), # 0x200 Mode register set command update delay >=0x80
                                                     ('reg_ddrc_ddr3',            (0,1)[is_DDR3]), # 0x1 0 - DDR2, 1 - DDR3
                                                     ('reg_ddrc_dis_auto_zq',     dis_auto_zq), # 0 DDR3 and LPDDR2 only: 1 - disable auto generation of ZQCS, 0 - enable'
                                                                                          ),force,warn)

# reg che_t_zq_short_interval_reg   dflt=0x0020003A act=0x690cb73
        rstn_x1024=              0x69   # using actual
        zq_short_interval_x1024= 0xcb73 # using actual
        ddrc_register_set.set_bitfields('che_t_zq_short_interval_reg',(
                                                     ('dram_rstn_x1024',            rstn_x1024), # 0x69 DDR3 only: Number of cycles to assert reset during init sequence (in 1024 cycles)
                                                     ('t_zq_short_interval_x1024',  zq_short_interval_x1024), # 0xcb73 DDR3 and LPDDR2 only: AVerage interval between automatic ZQCS in 1024 clock cycles
                                                                                     ),force,warn)

# reg deep_pwrdwn_reg       dflt=0 act=0x1fe
        deeppowerdown_to_x1024=0xff # LPDDR2 only, using actual
        ddrc_register_set.set_bitfields('deep_pwrdwn_reg',(
                                                     ('deeppowerdown_to_x1024',deeppowerdown_to_x1024), # 0xff LPDDR2 only: minimal deep power down time in 1024 clk (specs - 500usec)
                                                     ('deeppowerdown_en',            0), # 0 LPDDR2 only: 0 - normal, 1 - go to deep power down when transaction store is empty
                                                                                      ),force,warn)

# reg  reg_2c   dflt=0 act=0xffffff
886 887 888 889
#        use_rd_data_eye_level = (0,1)[self.features.get_par_value('TRAIN_DATA_EYE')] 
#        use_rd_dqs_gate_level = (0,1)[self.features.get_par_value('TRAIN_READ_GATE')] 
#        use_wr_level          = (0,1)[self.features.get_par_value('TRAIN_WRITE_LEVEL')] 

890 891
        dfi_rdlvl_max_x1024=0xfff # using actual/recommended
        dfi_wrlvl_max_x1024=0xfff # using actual/recommended
892
        #Vivado 2013.3 set DFI training to 1
893
        ddrc_register_set.set_bitfields('reg_2c',(
894 895 896
                                                     ('reg_ddrc_dfi_rd_data_eye_train', use_rd_data_eye_level), # 0 DDR3 and LPDDR2 only: 1 - read data eye training (part of init sequence)
                                                     ('reg_ddrc_dfi_rd_dqs_gate_level', use_rd_dqs_gate_level), # 0 1 - Read DQS gate leveling mode (DDR3 DFI only)
                                                     ('reg_ddrc_dfi_wr_level_en',        use_wr_level), # 0 1 - Write leveling mode (DDR3 DFI only)
897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921
                                                     ('ddrc_reg_trdlvl_max_error',      0), # 0 READONLY: DDR3 and LPDDR2 only: leveling/gate training timeout (clear on write)
                                                     ('ddrc_reg_twrlvl_max_error',      0), # 0 READONLY: DDR3 only: write leveling timeout (clear on write) 
                                                     ('dfi_rdlvl_max_x1024',dfi_rdlvl_max_x1024), # 0xfff Read leveling maximal time in 1024 clk. Typical value 0xFFF
                                                     ('dfi_wrlvl_max_x1024',dfi_wrlvl_max_x1024), # 0xfff Write leveling maximal time in 1024 clk. Typical value 0xFFF
                                                                                          ),force,warn)

# reg   reg_2d   dflt=0x200 act=0x200
        ddrc_register_set.set_bitfields('reg_2d',(
                                                     ('reg_ddrc_dis_pre_bypass',  0),  # 0 reserved
                                                     ('reg_ddrc_skip_ocd',        0x1),# 0x1 should be 1, 0 is not supported. 1 - skip OCD adjustment step during DDR2 init,  use OCD_Default and OCD_exit
                                                     ('reg_ddrc_2t_delay',        0),  # 0 reserved
                                                                                   ),force,warn)

# reg  dfi_timimg  dflt=0x00200067 act=0x0x200066
        dfi_t_ctrlup_max=0x40 # using actual for (ddr3), not clear how to calculate
        dfi_t_ctrlup_min=0x3  # using actual for (ddr3), not clear how to calculate
        if is_DDR2 or is_DDR3:
            dfi_t_rddata_en=RL-1
        elif is_LPDDR2:
            dfi_t_rddata_en=RL
        ddrc_register_set.set_bitfields('dfi_timimg',(
                                                     ('reg_ddrc_dfi_t_ctrlup_max', dfi_t_ctrlup_max), # 0x40 Maximal number of clocks  ddrc_dfi_ctrlupd_req can assert
                                                     ('reg_ddrc_dfi_t_ctrlup_min', dfi_t_ctrlup_min), # 0x3 Minimal number of clocks  ddrc_dfi_ctrlupd_req must be asserted
                                                     ('reg_ddrc_dfi_t_rddata_en',  dfi_t_rddata_en), # 0x6 LPDDR2 - RL, DDR2 and DDR3 - RL-1
                                                                                     ),force,warn)
Andrey Filippov's avatar
Andrey Filippov committed
922 923 924 925
#ECC control, can probably be skipped?
        programECC = True        
        if programECC:
# reg  che_ecc_control_reg_offset (offs=0xc4) : 0 - always, ==dflt
926 927 928 929 930
            ddrc_register_set.set_bitfields('che_ecc_control_reg_offset',(
                                                     ('clear_correctable_dram_ecc_error', 1), # 0 1 - clear correctable log (valid+counters)
                                                     ('clear_uncorrectable_dram_ecc_error', 1), # 0  1 - clear uncorrectable log (valid+counters)
                                                                                     ),force,warn)
            ddrc_register_set.flush()
Andrey Filippov's avatar
Andrey Filippov committed
931 932 933 934
            ddrc_register_set.set_bitfields('che_ecc_control_reg_offset',(
                                                     ('clear_correctable_dram_ecc_error', 0), # 0 1 - clear correctable log (valid+counters)
                                                     ('clear_uncorrectable_dram_ecc_error', 0), # 0  1 - clear uncorrectable log (valid+counters)
                                                                                     ),force,warn)
935

Andrey Filippov's avatar
Andrey Filippov committed
936 937 938 939 940 941 942 943 944 945 946 947 948 949 950
# reg che_corr_ecc_log_reg_offset (offs=0xc8): 0 - always, ==dflt
            ddrc_register_set.set_bitfields('che_corr_ecc_log_reg_offset',(
                                                     ('ecc_corrected_bit_num', 0), # 0 - encoded error bits for up to 72-bit data (clear on write)
#                                                     ('corr_ecc_log_valid', 0), # 0 - READONLY corr_ecc_log_valid
                                                                                     ),force,warn)

# reg che_corr_ecc_addr_reg_offset: READONLY  
#        ddrc_register_set.set_bitfields('che_corr_ecc_addr_reg_offset',(
#                                                     ('corr_ecc_log_bank', 0), # 0
#                                                     ('corr_ecc_log_row', 0), # 0
#                                                     ('corr_ecc_log_col', 0), # 0
#                                                                                     ),force,warn)

# reg che_corr_ecc_data_31_0_reg_offset: READONLY                                                                                   
#            ddrc_register_set.set_bitfields('che_corr_ecc_data_31_0_reg_offset',(('corr_ecc_dat_31_0', 0)),force,warn)
951

Andrey Filippov's avatar
Andrey Filippov committed
952 953
# reg  che_corr_ecc_data_63_32_reg_offset: READONLY
#            ddrc_register_set.set_bitfields('che_corr_ecc_data_63_32_reg_offset',(('corr_ecc_dat_63_32', 0)),force,warn) #0 bits[32:63] of the word with correctable ECC error. actually all are 0'
954

Andrey Filippov's avatar
Andrey Filippov committed
955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063
# reg  che_corr_ecc_data_71_64_reg_offset: READONLY
#            ddrc_register_set.set_bitfields('che_corr_ecc_data_71_64_reg_offset',(('corr_ecc_dat_71_64', 0)),force,warn) #0 bits[64:71] of the word with correctable ECC error. only lower 5 bits have data, the rest are 0

# reg  che_uncorr_ecc_log_reg_offset (offset=0xdc): READONLY 
#            ddrc_register_set.set_bitfields('che_uncorr_ecc_log_reg_offset',(('uncorr_ecc_log_valid', 0)),force,warn) # Set to 1 when uncorrectable error is capture (no more captured until cleared), cleared by che_ecc_control_reg_offset

# reg che_uncorr_ecc_addr_reg_offset : READONLY
#            ddrc_register_set.set_bitfields('che_uncorr_ecc_addr_reg_offset',(
#                                                     ('uncorr_ecc_log_bank', 0), # 0
#                                                     ('uncorr_ecc_log_row', 0), # 0
#                                                     ('uncorr_ecc_log_col', 0)),force,warn) , # 0

# reg uncorr_ecc_dat_31_0: READONLY       
#            ddrc_register_set.set_bitfields('uncorr_ecc_dat_31_0',(('reserved1', 0)),force,warn) # bits[0:31] of the word with uncorrectable ECC error. actually only 0:7 have valid data, 8:31 are 0

# reg  che_uncorr_ecc_data_63_32_reg_offset: READONLY
#            ddrc_register_set.set_bitfields('che_uncorr_ecc_data_63_32_reg_offset',(('reserved1', 0)),force,warn) # bits[32:63] of the word with uncorrectable ECC error. actually all are 0

# reg  che_uncorr_ecc_data_71_64_reg_offset: READONLY
#            ddrc_register_set.set_bitfields('che_uncorr_ecc_data_71_64_reg_offset',(('reserved1', 0)),force,warn) # bits[64:71] of the word with uncorrectable ECC error. only lower 5 bits have data, the rest are 0

# reg  che_ecc_stats_reg_offset (offset=0xf0): Clear on write
#     'che_ecc_stats_reg_offset':{'OFFS': 0x0F0,'DFLT':0x00000000,'RW':'CW', 'FIELDS':{ # 0x0
#                   'stat_num_corr_err':                {'r':( 8,15),'d':0,'m':'R','c':'Number of correctable ECC errors since 1 written to bit 1 of che_ecc_control_reg_offset (0xC4)'},       
#                   'stat_num_uncorr_err':              {'r':( 0, 7),'d':0,'m':'R','c':'Number of uncorrectable ECC errors since 1 written to bit 0 of che_ecc_control_reg_offset (0xC4)'}}},
            ddrc_register_set.set_bitfields('che_ecc_stats_reg_offset',(
                                                     ('stat_num_corr_err', 0), # Number of correctable ECC errors since 1 written to bit 1 of che_ecc_control_reg_offset (0xC4)
                                                     ('stat_num_uncorr_err', 0), # Number of uncorrectable ECC errors since 1 written to bit 0 of che_ecc_control_reg_offset (0xC4)
                                                                                     ),force,warn)
# reg  offs=0x0F8 che_ecc_corr_bit_mask_31_0_reg_offset : READONLY
#            ddrc_register_set.set_bitfields('che_ecc_corr_bit_mask_31_0_reg_offset',(('ddrc_reg_ecc_corr_bit_mask', 0)),force,warn) # bits[0:31] of the mask of the corrected data (1 - corrected, 0 - uncorrected). Only 0:7 have valid data, 8:31 are 0

# reg  offs=0x0FC che_ecc_corr_bit_mask_63_32_reg_offset : READONLY
#            ddrc_register_set.set_bitfields('che_ecc_corr_bit_mask_63_32_reg_offset',(('ddrc_reg_ecc_corr_bit_mask', 0)),force,warn) #bits[32:63] of the mask of the corrected data (1 - corrected, 0 - uncorrected). all bits are 0
# end of  if useECC:
# reg  ecc_scrub, offs=0x0F4 dflt:0x8 actual:0x8 (apply even with ECC disabled?)
#        
        ecc_mode=(0,4)[self.features.get_par_value('ECC')]
        ddrc_register_set.set_bitfields('ecc_scrub',(
                                                     ('reg_ddrc_dis_scrub', 1), # 1 1 - disable ECC scrubs, 0 - enable ECC scrubs
                                                     ('reg_ddrc_ecc_mode',  ecc_mode), # 0 DRAM ECC mode. Valid only 0(no ECC)  and 0x4 - "SEC/DED over 1-beat
                                                                                     ),force,warn)
# reg  phy_rcvr_enable, offs=0x114 dflt:0 actual:0
#     'phy_rcvr_enable':         {'OFFS': 0x114,'DFLT':0x00000000,'RW':'RW','FIELDS':{ # 0x0
#                   'reg_phy_dif_off':                  {'r':( 4, 7),'d':0,'c':'"Off" value of the drive of the receiver-enabled pins'},       
#                   'reg_phy_dif_on':                   {'r':( 0, 3),'d':0,'c':'"On" value of the drive of the receiver-enabled pins'}}},
        ddrc_register_set.set_bitfields('phy_rcvr_enable',(
                                                     ('reg_phy_dif_off', 0), # 0 - "Off" value of the drive of the receiver-enabled pins
                                                     ('reg_phy_dif_on', 0),  # 0 - "On" value of the drive of the receiver-enabled pins
                                                                                     ),force,warn)
#PHY configuration for each of 4 8-bit dta slices, I guess:
        slice_in_use0=1
        slice_in_use1=1
        slice_in_use2=(1,0)[half_width]
        slice_in_use3=(1,0)[half_width]

# reg  phy_config0, offs=0x118 dflt:0x40000001 actual:0x40000001
        ddrc_register_set.set_bitfields('phy_config0',( # PHY configuration for data slice 0
                                                     ('reg_phy_dq_offset',    0x40),  # 0x40  Offset value of DQS to DQ during write leveling of data slice 0. Default is 0x40 for 90-degree shift 
                                                     ('reg_phy_bist_err_clr',    0),  # 
                                                     ('reg_phy_bist_shift_dq',   0),  # 
                                                     ('reg_phy_board_lpbk_rx',   0),  # 
                                                     ('reg_phy_board_lpbk_tx',   0),  # 
                                                     ('reg_phy_wrlvl_inc_mode',  0),  # 
                                                     ('reg_phy_gatelvl_inc_mode',0),  # 
                                                     ('reg_phy_rdlvl_inc_mode',  0),  # 
                                                     ('reg_phy_rdlvl_inc_mode',  0),  # 
                                                     ('reg_phy_data_slice_in_use',slice_in_use0), # 1 Data bus width for read FIFO generation. 0 - read data responses are ignored, 1 - data slice 0 is valid (always 1)
                                                                                     ),force,warn)

# reg  phy_config1, offs=0x11c dflt:0x40000001 actual:0x40000001
        ddrc_register_set.set_bitfields('phy_config1',( # PHY configuration for data slice 0
                                                     ('reg_phy_dq_offset',    0x40),  # 0x40  Offset value of DQS to DQ during write leveling of data slice 1. Default is 0x40 for 90-degree shift 
                                                     ('reg_phy_bist_err_clr',    0),  # 
                                                     ('reg_phy_bist_shift_dq',   0),  # 
                                                     ('reg_phy_board_lpbk_rx',   0),  # 
                                                     ('reg_phy_board_lpbk_tx',   0),  # 
                                                     ('reg_phy_wrlvl_inc_mode',  0),  # 
                                                     ('reg_phy_gatelvl_inc_mode',0),  # 
                                                     ('reg_phy_rdlvl_inc_mode',  0),  # 
                                                     ('reg_phy_rdlvl_inc_mode',  0),  # 
                                                     ('reg_phy_data_slice_in_use',slice_in_use1), # 1 Data bus width for read FIFO generation. 0 - read data responses are ignored, 1 - data slice 1 is valid (always 1)
                                                                                     ),force,warn)
# reg  phy_config2, offs=0x120 dflt:0x40000001 actual:0x40000001
        ddrc_register_set.set_bitfields('phy_config2',( # PHY configuration for data slice 0
                                                     ('reg_phy_dq_offset',    0x40),  # 0x40  Offset value of DQS to DQ during write leveling of data slice 2. Default is 0x40 for 90-degree shift 
                                                     ('reg_phy_bist_err_clr',    0),  # 
                                                     ('reg_phy_bist_shift_dq',   0),  # 
                                                     ('reg_phy_board_lpbk_rx',   0),  # 
                                                     ('reg_phy_board_lpbk_tx',   0),  # 
                                                     ('reg_phy_wrlvl_inc_mode',  0),  # 
                                                     ('reg_phy_gatelvl_inc_mode',0),  # 
                                                     ('reg_phy_rdlvl_inc_mode',  0),  # 
                                                     ('reg_phy_rdlvl_inc_mode',  0),  # 
                                                     ('reg_phy_data_slice_in_use',slice_in_use2), # 1 Data bus width for read FIFO generation. 0 - read data responses are ignored, 1 - data slice 2 is valid (always 1)
                                                                                     ),force,warn)
# reg  phy_config3, offs=0x124 dflt:0x40000001 actual:0x40000001
        ddrc_register_set.set_bitfields('phy_config3',( # PHY configuration for data slice 0
                                                     ('reg_phy_dq_offset',    0x40),  # 0x40  Offset value of DQS to DQ during write leveling of data slice 3. Default is 0x40 for 90-degree shift 
                                                     ('reg_phy_bist_err_clr',    0),  # 
                                                     ('reg_phy_bist_shift_dq',   0),  # 
                                                     ('reg_phy_board_lpbk_rx',   0),  # 
                                                     ('reg_phy_board_lpbk_tx',   0),  # 
                                                     ('reg_phy_wrlvl_inc_mode',  0),  # 
                                                     ('reg_phy_gatelvl_inc_mode',0),  # 
                                                     ('reg_phy_rdlvl_inc_mode',  0),  # 
                                                     ('reg_phy_rdlvl_inc_mode',  0),  # 
                                                     ('reg_phy_data_slice_in_use',slice_in_use3), # 1 Data bus width for read FIFO generation. 0 - read data responses are ignored, 1 - data slice 3 is valid (always 1)
                                                                                     ),force,warn)
1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075
        gatelvl_init_ratio0=self.features.get_par_value('PHY_GTLV_INIT_RATIO_0')
        gatelvl_init_ratio1=self.features.get_par_value('PHY_GTLV_INIT_RATIO_1')
        gatelvl_init_ratio2=self.features.get_par_value('PHY_GTLV_INIT_RATIO_2')
        gatelvl_init_ratio3=self.features.get_par_value('PHY_GTLV_INIT_RATIO_3')
          
        wrlvl_init_ratio0=self.features.get_par_value('PHY_WRLV_INIT_RATIO_0')
        wrlvl_init_ratio1=self.features.get_par_value('PHY_WRLV_INIT_RATIO_1')
        wrlvl_init_ratio2=self.features.get_par_value('PHY_WRLV_INIT_RATIO_2')
        wrlvl_init_ratio3=self.features.get_par_value('PHY_WRLV_INIT_RATIO_3')

        
        
Andrey Filippov's avatar
Andrey Filippov committed
1076 1077
# reg  phy_init_ratio0, offs=0x12C dflt:0x0 actual: 0x0
        ddrc_register_set.set_bitfields('phy_init_ratio0',( # PHY init ratio register for data slice 0
1078 1079
                                                     ('reg_phy_gatelvl_init_ratio',  gatelvl_init_ratio0),  # 0 User-programmable init ratio used by Gate Leveling FSM, data slice 0
                                                     ('reg_phy_wrlvl_init_ratio',    wrlvl_init_ratio0),  # 0 User-programmable init ratio used by Write Leveling FSM, data slice 0
Andrey Filippov's avatar
Andrey Filippov committed
1080 1081 1082
                                                                                     ),force,warn)
# reg  phy_init_ratio1, offs=0x130 dflt:0x0 actual: 0x0
        ddrc_register_set.set_bitfields('phy_init_ratio1',( # PHY init ratio register for data slice 1
1083 1084
                                                     ('reg_phy_gatelvl_init_ratio',  gatelvl_init_ratio1),  # 0 User-programmable init ratio used by Gate Leveling FSM, data slice 1
                                                     ('reg_phy_wrlvl_init_ratio',    wrlvl_init_ratio1),  # 0 User-programmable init ratio used by Write Leveling FSM, data slice 1
Andrey Filippov's avatar
Andrey Filippov committed
1085 1086 1087
                                                                                     ),force,warn)
# reg  phy_init_ratio2, offs=0x134 dflt:0x0 actual: 0x0
        ddrc_register_set.set_bitfields('phy_init_ratio2',( # PHY init ratio register for data slice 2
1088 1089
                                                     ('reg_phy_gatelvl_init_ratio',  gatelvl_init_ratio2),  # 0 User-programmable init ratio used by Gate Leveling FSM, data slice 2
                                                     ('reg_phy_wrlvl_init_ratio',    wrlvl_init_ratio2),  # 0 User-programmable init ratio used by Write Leveling FSM, data slice 2
Andrey Filippov's avatar
Andrey Filippov committed
1090 1091 1092
                                                                                     ),force,warn)
# reg  phy_init_ratio3, offs=0x138 dflt:0x0 actual: 0x0
        ddrc_register_set.set_bitfields('phy_init_ratio3',( # PHY init ratio register for data slice 3
1093 1094
                                                     ('reg_phy_gatelvl_init_ratio',  gatelvl_init_ratio3),  # 0 User-programmable init ratio used by Gate Leveling FSM, data slice 3
                                                     ('reg_phy_wrlvl_init_ratio',    wrlvl_init_ratio3),  # 0 User-programmable init ratio used by Write Leveling FSM, data slice 3
Andrey Filippov's avatar
Andrey Filippov committed
1095
                                                                                     ),force,warn)
1096 1097 1098 1099
        rd_dqs_slave_ratio0=0x35 # default=40
        rd_dqs_slave_ratio1=0x35 # default=40
        rd_dqs_slave_ratio2=0x35 # default=40
        rd_dqs_slave_ratio3=0x35 # default=40
Andrey Filippov's avatar
Andrey Filippov committed
1100 1101 1102 1103
# reg  phy_rd_dqs_cfg0, offs=0x140 dflt:0x40 actual: 0x35
        ddrc_register_set.set_bitfields('phy_rd_dqs_cfg0',( # PHY read DQS configuration register for data slice 0
                                                     ('reg_phy_rd_dqs_slave_delay',    0),  # 0 If reg_phy_rd_dqs_slave_force is 1, use this tap/delay value for read DQS slave DLL, data slice 0
                                                     ('reg_phy_rd_dqs_slave_force',    0),  # 0 0 - use reg_phy_rd_dqs_slave_ratio  for the read DQS slave DLL, 1 - use provided in reg_phy_rd_dqs_slave_delay, data slice 0
1104
                                                     ('reg_phy_rd_dqs_slave_ratio', rd_dqs_slave_ratio0),  # 0x35 Fraction of the clock cycle (256 = full period) for the read DQS slave DLL, data slice 0
Andrey Filippov's avatar
Andrey Filippov committed
1105 1106 1107 1108 1109
                                                                                     ),force,warn)
# reg  phy_rd_dqs_cfg1, offs=0x144 dflt:0x40 actual: 0x35
        ddrc_register_set.set_bitfields('phy_rd_dqs_cfg1',( # PHY read DQS configuration register for data slice 1
                                                     ('reg_phy_rd_dqs_slave_delay',    0),  # 0 If reg_phy_rd_dqs_slave_force is 1, use this tap/delay value for read DQS slave DLL, data slice 1
                                                     ('reg_phy_rd_dqs_slave_force',    0),  # 0 0 - use reg_phy_rd_dqs_slave_ratio  for the read DQS slave DLL, 1 - use provided in reg_phy_rd_dqs_slave_delay, data slice 1
1110
                                                     ('reg_phy_rd_dqs_slave_ratio', rd_dqs_slave_ratio1),  # 0x35 Fraction of the clock cycle (256 = full period) for the read DQS slave DLL, data slice 1
Andrey Filippov's avatar
Andrey Filippov committed
1111 1112 1113 1114 1115
                                                                                     ),force,warn)
# reg  phy_rd_dqs_cfg2, offs=0x148 dflt:0x40 actual: 0x35
        ddrc_register_set.set_bitfields('phy_rd_dqs_cfg2',( # PHY read DQS configuration register for data slice 2
                                                     ('reg_phy_rd_dqs_slave_delay',    0),  # 0 If reg_phy_rd_dqs_slave_force is 1, use this tap/delay value for read DQS slave DLL, data slice 2
                                                     ('reg_phy_rd_dqs_slave_force',    0),  # 0 0 - use reg_phy_rd_dqs_slave_ratio  for the read DQS slave DLL, 1 - use provided in reg_phy_rd_dqs_slave_delay, data slice 2
1116
                                                     ('reg_phy_rd_dqs_slave_ratio', rd_dqs_slave_ratio2),  # 0x35 Fraction of the clock cycle (256 = full period) for the read DQS slave DLL, data slice 2
Andrey Filippov's avatar
Andrey Filippov committed
1117 1118 1119 1120 1121
                                                                                     ),force,warn)
# reg  phy_rd_dqs_cfg3, offs=0x14c dflt:0x40 actual: 0x35
        ddrc_register_set.set_bitfields('phy_rd_dqs_cfg3',( # PHY read DQS configuration register for data slice 3
                                                     ('reg_phy_rd_dqs_slave_delay',    0),  # 0 If reg_phy_rd_dqs_slave_force is 1, use this tap/delay value for read DQS slave DLL, data slice 3
                                                     ('reg_phy_rd_dqs_slave_force',    0),  # 0 0 - use reg_phy_rd_dqs_slave_ratio  for the read DQS slave DLL, 1 - use provided in reg_phy_rd_dqs_slave_delay, data slice 3
1122
                                                     ('reg_phy_rd_dqs_slave_ratio', rd_dqs_slave_ratio3),  # 0x35 Fraction of the clock cycle (256 = full period) for the read DQS slave DLL, data slice 3
Andrey Filippov's avatar
Andrey Filippov committed
1123
                                                                                     ),force,warn)
1124 1125 1126 1127 1128 1129 1130
        
        wr_dqs_slave_ratio0=self.features.get_par_value('PHY_WR_DQS_SLAVE_RATIO_0')
        wr_dqs_slave_ratio1=self.features.get_par_value('PHY_WR_DQS_SLAVE_RATIO_1')
        wr_dqs_slave_ratio2=self.features.get_par_value('PHY_WR_DQS_SLAVE_RATIO_2')
        wr_dqs_slave_ratio3=self.features.get_par_value('PHY_WR_DQS_SLAVE_RATIO_3')
       
        
Andrey Filippov's avatar
Andrey Filippov committed
1131 1132 1133 1134
# reg  phy_wr_dqs_cfg0, offs=0x154 dflt:0 actual: 0
        ddrc_register_set.set_bitfields('phy_wr_dqs_cfg0',( # ,PHY write DQS configuration register for data slice 0
                                                     ('reg_phy_wr_dqs_slave_delay',  0),  # 0 If reg_phy_wr_dqs_slave_force is 1, use this tap/delay value for write DQS slave DLL, data slice 0
                                                     ('reg_phy_wr_dqs_slave_force',  0),  # 0 0 - use reg_phy_wr_dqs_slave_ratio  for the write DQS slave DLL, 1 - use provided in reg_phy_wr_dqs_slave_delay, data slice 0
1135
                                                     ('reg_phy_wr_dqs_slave_ratio',  wr_dqs_slave_ratio0),  # 0 Fraction of the clock cycle (256 = full period) for the write DQS slave DLL, data slice 0. Program manual training ratio
Andrey Filippov's avatar
Andrey Filippov committed
1136
                                                                                     ),force,warn)
1137
# reg  phy_wr_dqs_cfg1, offs=0x158 dflt:0 actual: 0
Andrey Filippov's avatar
Andrey Filippov committed
1138 1139 1140
        ddrc_register_set.set_bitfields('phy_wr_dqs_cfg1',( # ,PHY write DQS configuration register for data slice 1
                                                     ('reg_phy_wr_dqs_slave_delay',  0),  # 0 If reg_phy_wr_dqs_slave_force is 1, use this tap/delay value for write DQS slave DLL, data slice 1
                                                     ('reg_phy_wr_dqs_slave_force',  0),  # 0 0 - use reg_phy_wr_dqs_slave_ratio  for the write DQS slave DLL, 1 - use provided in reg_phy_wr_dqs_slave_delay, data slice 1
1141
                                                     ('reg_phy_wr_dqs_slave_ratio',  wr_dqs_slave_ratio1),  # 0 Fraction of the clock cycle (256 = full period) for the write DQS slave DLL, data slice 1. Program manual training ratio
Andrey Filippov's avatar
Andrey Filippov committed
1142
                                                                                     ),force,warn)
1143
# reg  phy_wr_dqs_cfg2, offs=0x15c dflt:0 actual: 0
Andrey Filippov's avatar
Andrey Filippov committed
1144 1145 1146
        ddrc_register_set.set_bitfields('phy_wr_dqs_cfg2',( # ,PHY write DQS configuration register for data slice 2
                                                     ('reg_phy_wr_dqs_slave_delay',  0),  # 0 If reg_phy_wr_dqs_slave_force is 1, use this tap/delay value for write DQS slave DLL, data slice 2
                                                     ('reg_phy_wr_dqs_slave_force',  0),  # 0 0 - use reg_phy_wr_dqs_slave_ratio  for the write DQS slave DLL, 1 - use provided in reg_phy_wr_dqs_slave_delay, data slice 2
1147
                                                     ('reg_phy_wr_dqs_slave_ratio',  wr_dqs_slave_ratio2),  # 0 Fraction of the clock cycle (256 = full period) for the write DQS slave DLL, data slice 2. Program manual training ratio
Andrey Filippov's avatar
Andrey Filippov committed
1148
                                                                                     ),force,warn)
1149
# reg  phy_wr_dqs_cfg3, offs=0x160 dflt:0 actual: 0
Andrey Filippov's avatar
Andrey Filippov committed
1150 1151 1152
        ddrc_register_set.set_bitfields('phy_wr_dqs_cfg3',( # ,PHY write DQS configuration register for data slice 3
                                                     ('reg_phy_wr_dqs_slave_delay',  0),  # 0 If reg_phy_wr_dqs_slave_force is 1, use this tap/delay value for write DQS slave DLL, data slice 3
                                                     ('reg_phy_wr_dqs_slave_force',  0),  # 0 0 - use reg_phy_wr_dqs_slave_ratio  for the write DQS slave DLL, 1 - use provided in reg_phy_wr_dqs_slave_delay, data slice 3
1153
                                                     ('reg_phy_wr_dqs_slave_ratio',  wr_dqs_slave_ratio3),  # 0 Fraction of the clock cycle (256 = full period) for the write DQS slave DLL, data slice 3. Program manual training ratio
Andrey Filippov's avatar
Andrey Filippov committed
1154
                                                                                     ),force,warn)
1155 1156 1157 1158 1159

        fifo_we_slave_ratio0=self.features.get_par_value('PHY_FIFO_WE_SLAVE_RATIO_0')
        fifo_we_slave_ratio1=self.features.get_par_value('PHY_FIFO_WE_SLAVE_RATIO_1')
        fifo_we_slave_ratio2=self.features.get_par_value('PHY_FIFO_WE_SLAVE_RATIO_2')
        fifo_we_slave_ratio3=self.features.get_par_value('PHY_FIFO_WE_SLAVE_RATIO_3')
Andrey Filippov's avatar
Andrey Filippov committed
1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184
        
# reg  phy_we_cfg0, offs=0x168 dflt:0x40 actual: 0x35
        ddrc_register_set.set_bitfields('phy_we_cfg0',( # PHY FIFO write enable configuration register for data slice 0
                                                     ('reg_phy_fifo_we_in_delay',  0),  # 0 If reg_phy_fifo_we_in_force is 1, use this tap/delay value for fifo_we_0 slave DLL, data slice 0
                                                     ('reg_phy_fifo_we_in_force',  0),  # 0 0 - use reg_phy_fifo_we_slave_ratio for fifo_we_0 slave DLL, 1 - use provided in reg_phy_fifo_we_in_delay, data slice 0
                                                     ('reg_phy_fifo_we_slave_ratio',fifo_we_slave_ratio0),  # 0x35 Fraction of the clock cycle (256 = full period) for fifo_we_0 slave DLL, data slice 0. Program manual training ratio
                                                                                     ),force,warn)
# reg  phy_we_cfg0, offs=0x16c dflt:0x40 actual: 0x35
        ddrc_register_set.set_bitfields('phy_we_cfg1',( # PHY FIFO write enable configuration register for data slice 1
                                                     ('reg_phy_fifo_we_in_delay',  0),  # 0 If reg_phy_fifo_we_in_force is 1, use this tap/delay value for fifo_we_0 slave DLL, data slice 1
                                                     ('reg_phy_fifo_we_in_force',  0),  # 0 0 - use reg_phy_fifo_we_slave_ratio for fifo_we_0 slave DLL, 1 - use provided in reg_phy_fifo_we_in_delay, data slice 1
                                                     ('reg_phy_fifo_we_slave_ratio',fifo_we_slave_ratio1),  # 0x35 Fraction of the clock cycle (256 = full period) for fifo_we_0 slave DLL, data slice 1. Program manual training ratio
                                                                                     ),force,warn)
# reg  phy_we_cfg0, offs=0x170 dflt:0x40 actual: 0x35
        ddrc_register_set.set_bitfields('phy_we_cfg2',( # PHY FIFO write enable configuration register for data slice 2
                                                     ('reg_phy_fifo_we_in_delay',  0),  # 0 If reg_phy_fifo_we_in_force is 1, use this tap/delay value for fifo_we_0 slave DLL, data slice 2
                                                     ('reg_phy_fifo_we_in_force',  0),  # 0 0 - use reg_phy_fifo_we_slave_ratio for fifo_we_0 slave DLL, 1 - use provided in reg_phy_fifo_we_in_delay, data slice 2
                                                     ('reg_phy_fifo_we_slave_ratio',fifo_we_slave_ratio2),  # 0x35 Fraction of the clock cycle (256 = full period) for fifo_we_0 slave DLL, data slice 2. Program manual training ratio
                                                                                     ),force,warn)
# reg  phy_we_cfg0, offs=0x174 dflt:0x40 actual: 0x35
        ddrc_register_set.set_bitfields('phy_we_cfg3',( # PHY FIFO write enable configuration register for data slice 3
                                                     ('reg_phy_fifo_we_in_delay',  0),  # 0 If reg_phy_fifo_we_in_force is 1, use this tap/delay value for fifo_we_0 slave DLL, data slice 3
                                                     ('reg_phy_fifo_we_in_force',  0),  # 0 0 - use reg_phy_fifo_we_slave_ratio for fifo_we_0 slave DLL, 1 - use provided in reg_phy_fifo_we_in_delay, data slice 3
                                                     ('reg_phy_fifo_we_slave_ratio',fifo_we_slave_ratio3),  # 0x35 Fraction of the clock cycle (256 = full period) for fifo_we_0 slave DLL, data slice 3. Program manual training ratio
                                                                                     ),force,warn)
1185 1186 1187 1188
        wr_data_slave_ratio0=self.features.get_par_value('PHY_WR_DATA_SLAVE_RATIO_0')
        wr_data_slave_ratio1=self.features.get_par_value('PHY_WR_DATA_SLAVE_RATIO_1')
        wr_data_slave_ratio2=self.features.get_par_value('PHY_WR_DATA_SLAVE_RATIO_2')
        wr_data_slave_ratio3=self.features.get_par_value('PHY_WR_DATA_SLAVE_RATIO_3')
Andrey Filippov's avatar
Andrey Filippov committed
1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213
# reg  wr_data_slv0, offs=0x17c dflt:0x80 actual: 0x40
        ddrc_register_set.set_bitfields('wr_data_slv0',( # PHY write data slave ratio configuration register for data slice 0
                                                     ('reg_phy_wr_data_slave_delay',  0),  # 0 If reg_phy_wr_dqs_slave_force is 1, use this tap/delay value for write data slave DLL, data slice 0
                                                     ('reg_phy_wr_data_slave_force',  0),  # 0 0 - use reg_phy_wr_dqs_slave_ratio  for the write data slave DLL, 1 - use provided in reg_phy_wr_dqs_slave_delay, data slice 0
                                                     ('reg_phy_wr_data_slave_ratio',wr_data_slave_ratio0),  # 0x40 Fraction of the clock cycle (256 = full period) for the write data slave DLL, data slice 0. Program manual training ratio
                                                                                     ),force,warn)
# reg  wr_data_slv1, offs=0x180 dflt:0x80 actual: 0x40
        ddrc_register_set.set_bitfields('wr_data_slv1',( # PHY write data slave ratio configuration register for data slice 1
                                                     ('reg_phy_wr_data_slave_delay',  0),  # 0 If reg_phy_wr_dqs_slave_force is 1, use this tap/delay value for write data slave DLL, data slice 1
                                                     ('reg_phy_wr_data_slave_force',  0),  # 0 0 - use reg_phy_wr_dqs_slave_ratio  for the write data slave DLL, 1 - use provided in reg_phy_wr_dqs_slave_delay, data slice 1
                                                     ('reg_phy_wr_data_slave_ratio',wr_data_slave_ratio1),  # 0x40 Fraction of the clock cycle (256 = full period) for the write data slave DLL, data slice 1. Program manual training ratio
                                                                                     ),force,warn)
# reg  wr_data_slv2, offs=0x184 dflt:0x80 actual: 0x40
        ddrc_register_set.set_bitfields('wr_data_slv2',( # PHY write data slave ratio configuration register for data slice 2
                                                     ('reg_phy_wr_data_slave_delay',  0),  # 0 If reg_phy_wr_dqs_slave_force is 1, use this tap/delay value for write data slave DLL, data slice 2
                                                     ('reg_phy_wr_data_slave_force',  0),  # 0 0 - use reg_phy_wr_dqs_slave_ratio  for the write data slave DLL, 1 - use provided in reg_phy_wr_dqs_slave_delay, data slice 2
                                                     ('reg_phy_wr_data_slave_ratio',wr_data_slave_ratio2),  # 0x40 Fraction of the clock cycle (256 = full period) for the write data slave DLL, data slice 2. Program manual training ratio
                                                                                     ),force,warn)
# reg  wr_data_slv3, offs=0x188 dflt:0x80 actual: 0x40
        ddrc_register_set.set_bitfields('wr_data_slv3',( # PHY write data slave ratio configuration register for data slice 3
                                                     ('reg_phy_wr_data_slave_delay',  0),  # 0 If reg_phy_wr_dqs_slave_force is 1, use this tap/delay value for write data slave DLL, data slice 3
                                                     ('reg_phy_wr_data_slave_force',  0),  # 0 0 - use reg_phy_wr_dqs_slave_ratio  for the write data slave DLL, 1 - use provided in reg_phy_wr_dqs_slave_delay, data slice 3
                                                     ('reg_phy_wr_data_slave_ratio',wr_data_slave_ratio3),  # 0x40 Fraction of the clock cycle (256 = full period) for the write data slave DLL, data slice 3. Program manual training ratio
                                                                                     ),force,warn)
# reg  reg_64, offs=0x190 dflt:0x10020000 actual:0x20000(first time)-0x10020000-0x10020000
1214
        use_rank0_delays = (1,0)[self.silicon==3] # marked as reserved, but actually is first set to 0 - maybe not needed
Andrey Filippov's avatar
Andrey Filippov committed
1215
        phy_lpddr=       (0,1)[is_LPDDR2]
1216
        phy_ctrl_slave_ratio=self.features.get_par_value('PHY_CTRL_SLAVE_RATIO') # 0x80 # default/actual
Andrey Filippov's avatar
Andrey Filippov committed
1217
        sel_logic       = 0 # Read leveling algorithm select - 0:algorithm 1, 1: algorithm 2 
1218 1219 1220 1221 1222 1223
        phy_invert_clkout=self.features.get_par_value('PHY_INVERT_CLK')
#define CONFIG_EZYNQ_PHY_PHY_CTRL_SLAVE_RATIO 0x100     /* Ratio for address/command (256 - clock period) */
#define CONFIG_EZYNQ_PHY_INVERT_CLK                     /* RInvert CLK out (if clk can arrive to DRAM chip earlier/at the same time as DQS) */
        
        
        
Andrey Filippov's avatar
Andrey Filippov committed
1224 1225 1226 1227 1228 1229 1230
        ddrc_register_set.set_bitfields('reg_64',( # Training control 2
                                                     ('reg_phy_int_lpbk',          0),  # reserved
                                                     ('reg_phy_cmd_latency',       0),  # 1: Delay command to PHY by a FF
                                                     ('reg_phy_lpddr',     phy_lpddr),  # 0: DDR2/DDR3, 1 - LPDDR2
                                                     ('reg_phy_use_rank0_delays', use_rank0_delays),  # reserved
                                                     ('reg_phy_ctrl_slave_delay',  0),  # when reg_phy_rd_dqs_slave_force==1 this value (combined with bits 18:19 of reg_65) set address/command slave DLL
                                                     ('reg_phy_ctrl_slave_force',  0),  # 0:use reg_phy_ctrl_slave_ratio for addr/cmd slave DLL, 1 - overwrite with reg_phy_ctrl_slave_delay
1231
                                                     ('reg_phy_ctrl_slave_ratio',phy_ctrl_slave_ratio), # address/command delay in clock/256
Andrey Filippov's avatar
Andrey Filippov committed
1232 1233
                                                     ('reg_phy_sel_logic', sel_logic),  # Read leveling algorithm select - 0:algorithm 1, 1: algorithm 2
                                                     ('reg_phy_all_dq_mpr_rd_resp',0),  # reserved
1234
                                                     ('reg_phy_invert_clkout',     phy_invert_clkout),  # 1 - invert clock polarity to DRAM
Andrey Filippov's avatar
Andrey Filippov committed
1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257
                                                     ('reg_phy_bist_mode',         0),  # reserved
                                                     ('reg_phy_bist_force_err',    0),  # reserved
                                                     ('reg_phy_bist_enable',       0),  # reserved
                                                     ('reg_phy_at_spd_atpg',       0),  # reserved
                                                     ('reg_phy_bl2',               0),  # reserved
                                                     ('reg_phy_loopback',          0),  # reserved
                                                                                     ),force,warn)
# reg  reg_65, offs=0x194 dflt:0 actual: 0x3c82
        dll_lock_diff =         0xf #default/actual
        rd_rl_delay   = max(RL-3,1) # 0x4
        wr_rl_delay   = max(WL-4,1) # 0x2
        
# TODO: Maybe more changes are needed to use training, generate ps7* with training enabled and compare results
        ddrc_register_set.set_bitfields('reg_65',( # Training control 3
                                                     ('reg_phy_ctrl_slave_delay',                         0),  # when reg_phy_rd_dqs_slave_force==1 this value (combined with bits 21:27 of reg_64) set address/command slave DLL'},
                                                     ('reg_phy_dis_calib_rst',                            0),  # disable dll_calib from resetting Read Capture FIFO
                                                     ('reg_phy_use_rd_data_eye_level',use_rd_data_eye_level),  # Read Data Eye training control - 0 use fixed register data, 1 use data eye leveling data
                                                     ('reg_phy_use_rd_dqs_gate_level',use_rd_dqs_gate_level),  # Read DQS Gate training control: 0 - used fixed data, 1 - use calculated data
                                                     ('reg_phy_use_wr_level',                  use_wr_level),  # Write leveling control: 0 - used programmed register data, 1 - use calculated data
                                                     ('reg_phy_dll_lock_diff',                dll_lock_diff),  # 0xf Maximal number of DLL taps before DLL deasserts lock
                                                     ('reg_phy_rd_rl_delay',                    rd_rl_delay),  # 0x4
                                                     ('reg_phy_wr_rl_delay',                    wr_rl_delay),  # 0x2
                                                                                     ),force,warn)
1258 1259 1260 1261




Andrey Filippov's avatar
Andrey Filippov committed
1262 1263 1264 1265 1266
# reg  page_mask, offs=0x204 dflt:0 actual: 0
#        page_addr_mask=0 # disable prioritization based on page/bank match 
        ddrc_register_set.set_bitfields('page_mask',( # Arbiter Page Mask
                                                     ('reg_arb_page_addr_mask',page_addr_mask),  # Arbiter page hit/miss: 0 - column address, 1 - row/bank address (applies to 64-bit address, not byte addr)
                                                                                     ),force,warn)
1267

Andrey Filippov's avatar
Andrey Filippov committed
1268 1269 1270 1271 1272 1273
        arb_pri_wr_port0=0x3ff # lowest 
        arb_pri_wr_port1=0x3ff # lowest 
        arb_pri_wr_port2=0x3ff # lowest 
        arb_pri_wr_port3=0x3ff # lowest 
# reg  axi_priority_wr_port0, offs=0x208 dflt:0x803FF actual: 0x803ff
        ddrc_register_set.set_bitfields('axi_priority_wr_port0',( # AXI priority control for write port 0
1274
                                                     ('reserved1',                     (1,0)[self.silicon==3]),  # 0x1
Andrey Filippov's avatar
Andrey Filippov committed
1275 1276 1277 1278 1279 1280
                                                     ('reg_arb_dis_page_match_wr_portn', 0),  # Disable page match feature
                                                     ('reg_arb_disable_urgent_wr_portn', 0),  # Disable urgent for this Write Port
                                                     ('reg_arb_disable_aging_wr_portn',  0),  # Disable aging for this Write Port
                                                     ('reserved2',                       0),  #
                                                     ('reg_arb_pri_wr_portn',arb_pri_wr_port0),  # 0x3ff Priority for this write port, >=4, lower value - higher priority
                                                                                            ),force,warn)
1281

Andrey Filippov's avatar
Andrey Filippov committed
1282 1283 1284
# reg  axi_priority_wr_port1, offs=0x20c dflt:0x803FF actual: 0x803ff
        ddrc_register_set.set_bitfields('axi_priority_wr_port1',( # AXI priority control for write port 1
                                                     ('reserved1', 0x1),  # 0x1
1285
                                                     ('reserved1',                     (1,0)[self.silicon==3]),  # 0x1
Andrey Filippov's avatar
Andrey Filippov committed
1286 1287 1288 1289 1290 1291 1292 1293
                                                     ('reg_arb_dis_page_match_wr_portn', 0),  # Disable page match feature
                                                     ('reg_arb_disable_urgent_wr_portn', 0),  # Disable urgent for this Write Port
                                                     ('reg_arb_disable_aging_wr_portn',  0),  # Disable aging for this Write Port
                                                     ('reserved2',                       0),  #
                                                     ('reg_arb_pri_wr_portn',arb_pri_wr_port1),  # 0x3ff Priority for this write port, >=4, lower value - higher priority
                                                                                            ),force,warn)
# reg  axi_priority_wr_port2, offs=0x210 dflt:0x803FF actual: 0x803ff
        ddrc_register_set.set_bitfields('axi_priority_wr_port2',( # AXI priority control for write port 2
1294
                                                     ('reserved1',                     (1,0)[self.silicon==3]),  # 0x1
Andrey Filippov's avatar
Andrey Filippov committed
1295 1296 1297 1298 1299 1300 1301 1302
                                                     ('reg_arb_dis_page_match_wr_portn', 0),  # Disable page match feature
                                                     ('reg_arb_disable_urgent_wr_portn', 0),  # Disable urgent for this Write Port
                                                     ('reg_arb_disable_aging_wr_portn',  0),  # Disable aging for this Write Port
                                                     ('reserved2',                       0),  #
                                                     ('reg_arb_pri_wr_portn',arb_pri_wr_port2),  # 0x3ff Priority for this write port, >=4, lower value - higher priority
                                                                                            ),force,warn)
# reg  axi_priority_wr_port3, offs=0x214 dflt:0x803FF actual: 0x803ff
        ddrc_register_set.set_bitfields('axi_priority_wr_port3',( # AXI priority control for write port 3
1303
                                                     ('reserved1',                     (1,0)[self.silicon==3]),  # 0x1
Andrey Filippov's avatar
Andrey Filippov committed
1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355
                                                     ('reg_arb_dis_page_match_wr_portn', 0),  # Disable page match feature
                                                     ('reg_arb_disable_urgent_wr_portn', 0),  # Disable urgent for this Write Port
                                                     ('reg_arb_disable_aging_wr_portn',  0),  # Disable aging for this Write Port
                                                     ('reserved2',                       0),  #
                                                     ('reg_arb_pri_wr_portn',arb_pri_wr_port3),  # 0x3ff Priority for this write port, >=4, lower value - higher priority
                                                                                            ),force,warn)
        arb_pri_rd_port0=0x3ff # lowest
        arb_pri_rd_port1=0x3ff # lowest
        arb_pri_rd_port2=0x3ff # lowest
        arb_pri_rd_port3=0x3ff # lowest
# reg  axi_priority_rd_port0, offs=0x218 dflt:0x3ff actual: 0x3ff
        ddrc_register_set.set_bitfields('axi_priority_rd_port0',( # AXI priority control for read port 0
                                                     ('reg_arb_set_hpr_rd_portn',        0),  # Enable reads to be HPR for this port
                                                     ('reg_arb_dis_page_match_rd_portn', 0),  # Disable page match feature
                                                     ('reg_arb_disable_urgent_rd_portn', 0),  # Disable urgent for this Read Port
                                                     ('reg_arb_disable_aging_rd_portn',  0),  # Disable aging for this Read Port
                                                     ('reserved1',                       0),  #
                                                     ('reg_arb_pri_rd_portn',arb_pri_rd_port0),  # 0x3ff Priority for this Read port, lower value - higher priority
                                                                                            ),force,warn)
# reg  axi_priority_rd_port1, offs=0x21c dflt:0x3ff actual: 0x3ff
        ddrc_register_set.set_bitfields('axi_priority_rd_port1',( # AXI priority control for read port 1
                                                     ('reg_arb_set_hpr_rd_portn',        0),  # Enable reads to be HPR for this port
                                                     ('reg_arb_dis_page_match_rd_portn', 0),  # Disable page match feature
                                                     ('reg_arb_disable_urgent_rd_portn', 0),  # Disable urgent for this Read Port
                                                     ('reg_arb_disable_aging_rd_portn',  0),  # Disable aging for this Read Port
                                                     ('reserved1',                       0),  #
                                                     ('reg_arb_pri_rd_portn',arb_pri_rd_port1),  # 0x3ff Priority for this Read port, lower value - higher priority
                                                                                            ),force,warn)
# reg  axi_priority_rd_port2, offs=0x220 dflt:0x3ff actual: 0x3ff
        ddrc_register_set.set_bitfields('axi_priority_rd_port2',( # AXI priority control for read port 2
                                                     ('reg_arb_set_hpr_rd_portn',        0),  # Enable reads to be HPR for this port
                                                     ('reg_arb_dis_page_match_rd_portn', 0),  # Disable page match feature
                                                     ('reg_arb_disable_urgent_rd_portn', 0),  # Disable urgent for this Read Port
                                                     ('reg_arb_disable_aging_rd_portn',  0),  # Disable aging for this Read Port
                                                     ('reserved1',                       0),  #
                                                     ('reg_arb_pri_rd_portn',arb_pri_rd_port2),  # 0x3ff Priority for this Read port, lower value - higher priority
                                                                                            ),force,warn)
# reg  axi_priority_rd_port3, offs=0x224 dflt:0x3ff actual: 0x3ff
        ddrc_register_set.set_bitfields('axi_priority_rd_port3',( # AXI priority control for read port 3
                                                     ('reg_arb_set_hpr_rd_portn',        0),  # Enable reads to be HPR for this port
                                                     ('reg_arb_dis_page_match_rd_portn', 0),  # Disable page match feature
                                                     ('reg_arb_disable_urgent_rd_portn', 0),  # Disable urgent for this Read Port
                                                     ('reg_arb_disable_aging_rd_portn',  0),  # Disable aging for this Read Port
                                                     ('reserved1',                       0),  #
                                                     ('reg_arb_pri_rd_portn',arb_pri_rd_port3),  # 0x3ff Priority for this Read port, lower value - higher priority
                                                                                            ),force,warn)
#Skipping several registers that are either obsolete or reserved 
#     'trusted_mem_cfg':         {'OFFS': 0x290,'DFLT':0x00000000,'RW':'RW','COMMENTS':'Trusted Memory Configuration (obsolete)','FIELDS':{
#     'excl_access_cfg0':        {'OFFS': 0x294,'DFLT':0x00000000,'RW':'RW','COMMENTS':'Exclusive access configuration for port 0','FIELDS':{
#     'excl_access_cfg1':        {'OFFS': 0x298,'DFLT':0x00000000,'RW':'RW','COMMENTS':'Exclusive access configuration for port 1','FIELDS':{
#     'excl_access_cfg2':        {'OFFS': 0x29C,'DFLT':0x00000000,'RW':'RW','COMMENTS':'Exclusive access configuration for port 2','FIELDS':{
#     'excl_access_cfg3':        {'OFFS': 0x2A0,'DFLT':0x00000000,'RW':'RW','COMMENTS':'Exclusive access configuration for port 3','FIELDS':{
1356

Andrey Filippov's avatar
Andrey Filippov committed
1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391
#Mobile DRAM settings - probably can be skipped if not is_LPDDR2? ps7* has them still programmed
# reg  lpddr_ctrl0, offs=0x2A8 dflt:0 actual: 0
        lpddr2_derate_enable=0 # This feature may be only enabled after LPDDR2 initialization is completed
        lpddr2=(0,1)[is_LPDDR2]
        ddrc_register_set.set_bitfields('lpddr_ctrl0',( # LPDDR2 control register 0 
                                                     ('reg_ddrc_mr4_margin',    0),  # unused
                                                     ('reserved1',              0),  # reserved
                                                     ('reg_ddrc_derate_enable', lpddr2_derate_enable),  # Timing parameter derating ENABLED using MR4 read data
                                                     ('reserved2',              0),  # reserved
                                                     ('reg_ddrc_lpddr2',   lpddr2),  # 0 - DDR2/DDR3 in use, 1 - LPDDR2 in use
                                                                                     ),force,warn)
# reg  lpddr_ctrl1, offs=0x2AC dflt:0 actual: 0
        ddrc_register_set.set_bitfields('lpddr_ctrl1',( # LPDDR2 control register 1
                                                     ('reg_ddrc_mr4_read_interval', 0),  #
                                                                                     ),force,warn)
# reg  lpddr_ctrl2, offs=0x2B0 dflt:0x3C0015 actual: 0x5125
        t_mrw=                  5
        idle_after_reset_x32=int(math.ceil(self.features.get_par_value('T_INIT4_US')*1000/tCK/32))   # 0x12
        min_stable_clock_x1 =   self.features.get_par_value('INIT2')  #0x5
        ddrc_register_set.set_bitfields('lpddr_ctrl2',( # LPDDR2 control register 2
                                                     ('reg_ddrc_t_mrw',                              t_mrw),  # 0x5  Wait for MR writes, typically required 5???
                                                     ('reg_ddrc_idle_after_reset_x32',idle_after_reset_x32),  # 0x12 Idle time after reset command, tINIT4 (in clockx32)
                                                     ('reg_ddrc_min_stable_clock_x1',  min_stable_clock_x1),  # 0x5  Time to wait after first CKE high, tINIT2 in clock cycles. Typically required 5 (tCK)
                                                                                     ),force,warn)
# reg  lpddr_ctrl3, offs=0x2B4 dflt:0x601 actual: 0x12a8
        #seems there is a BUG in ps7* calculation, the values are 32 times higher (as if max_auto_init_x1024 - is actually max_auto_init_x32)
        #Default value seems closer to result
        lpddr_ctrl3_BUG=1 #32 # change to 1 if confirmed
        dev_zqinit_x32=int(math.ceil(self.features.get_par_value('T_ZQINIT_US')*1000/tCK/32))         # 0x12
        max_auto_init_x1024=int(math.ceil(self.features.get_par_value('T_INIT5_US')*1000/tCK/1024*lpddr_ctrl3_BUG))   #0xa8
        ddrc_register_set.set_bitfields('lpddr_ctrl3',( # LPDDR2 control register 3
                                                     ('reg_ddrc_dev_zqinit_x32',          dev_zqinit_x32), # 0x1200 tZQINIT - ZQ initial calibration (in clockx32). LPDDR2 typically require 1 microsecond
                                                     ('reg_ddrc_max_auto_init_x1024',max_auto_init_x1024), # 0xa8    tINIT5 - maximal duration of autoinitialization (in clockx1024). Typical 10 microseconds
                                                                                     ),force,warn)
##########################################
1392

1393 1394 1395 1396
    def ddr_dci_calibrate(self,current_reg_sets,force=False,warn=False):
        ddriob_register_set=self.ddriob_register_set
        ddriob_register_set.set_initial_state(current_reg_sets, True)# start from the current registers state
        ddriob_register_set.set_bitfields('ddriob_dci_ctrl', ('reset',1),force,warn)        
1397
        ddriob_register_set.flush() # close previous register settings
1398
        ddriob_register_set.set_bitfields('ddriob_dci_ctrl', ('reset',0),force,warn)        
1399
        ddriob_register_set.flush()# close previous register settings
1400 1401
        ddriob_register_set.set_bitfields('ddriob_dci_ctrl', (('reset', 1),
                                                              ('enable',1),
1402
                                                              ('vrn_out',(1,0)[self.silicon==3]),
1403 1404 1405 1406 1407
                                                              ('nref_opt1',0),
                                                              ('nref_opt2',0),
                                                              ('nref_opt4',1),
                                                              ('pref_opt2',0),
                                                              ('update_control',0)),force,warn)
1408 1409
        ddriob_register_set.flush()# close previous register settings
        
1410 1411 1412
# add wait for DCI calibration DONE
        ddriob_register_set.wait_reg_field_values('ddriob_dci_status',('done',1), True, warn)

1413 1414 1415
        return ddriob_register_set.get_register_sets(True,True) # close previous register settings, return new result        


1416 1417
    def ddr_init_ddriob(self,force=False,warn=False): # will program to sequence 'MAIN'
#        print 'ddr_init_ddriob\n'
1418 1419
#        ddriob_register_set=self.ddriob_register_sets['MAIN']
        ddriob_register_set=self.ddriob_register_set
1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467
# DDRIOB configuration UG585.268
        is_LPDDR2=   (self.features.get_par_value('MEMORY_TYPE')=='LPDDR2')
        is_DDR3L=    (self.features.get_par_value('MEMORY_TYPE')=='DDR3L')
        is_DDR3_15=  (self.features.get_par_value('MEMORY_TYPE')=='DDR3')
        is_DDR3=     is_DDR3_15 or is_DDR3L
        is_DDR2=     (self.features.get_par_value('MEMORY_TYPE')=='DDR2')
        is_32=       (self.features.get_par_value('BUS_WIDTH') > 16)
        is_int_vref=  self.features.get_par_value('INTERNAL_VREF')
        
# Set the IOB configuration as follows:
        for reg_name in ('ddriob_addr0','ddriob_addr1','ddriob_data0','ddriob_data1','ddriob_diff0','ddriob_diff1','ddriob_clock'):
            ddriob_register_set.set_word(reg_name,0,force) # disable all        
#            ddriob_register_set.set_bitfields(reg_name,(('dco_type',0)),force,warn) # disable all - add other fields?        
# 1. Set DCI_TYPE to DCI Drive for all LPDDR2 I/Os.
        if is_LPDDR2:
            for reg_name in (('ddriob_addr0','ddriob_addr1','ddriob_data0','ddriob_diff0','ddriob_clock')
                             ('ddriob_addr0','ddriob_addr1','ddriob_data0','ddriob_data1','ddriob_diff0','ddriob_diff1','ddriob_clock'))[is_32]:
                ddriob_register_set.set_bitfields(reg_name,(('dco_type',1)),force,warn)        
# 2. Set DCI_TYPE to DCI Termination for DDR2/DDR3 bidirectional I/Os.
        if is_DDR2 or is_DDR3:
            for reg_name in (('ddriob_data0','ddriob_diff0'),
                             ('ddriob_data0','ddriob_data1','ddriob_diff0','ddriob_diff1'))[is_32]:
                ddriob_register_set.set_bitfields(reg_name,(('dci_type',3)),force,warn)   # 3 - DCI term (DDR2/3/3L DQ, DQS'
# 3. Set OUTPUT_EN = obuf to enable outputs.
        for reg_name in (('ddriob_addr0','ddriob_addr1','ddriob_data0','ddriob_diff0','ddriob_clock'),
                         ('ddriob_addr0','ddriob_addr1','ddriob_data0','ddriob_data1','ddriob_diff0','ddriob_diff1','ddriob_clock'))[is_32]:
            ddriob_register_set.set_bitfields(reg_name,(('output_en',3)),force,warn) # 3 - obuf        
# 4. Set TERM_DISABLE_MODE and IBUF_DISABLE_MODE to enable power saving input modes. The
#    TERM_DISABLE_MODE and IBUF_DISABLE_MODE fields should not be set before DDR training
#    has completed.
        # do nothing now
# 5. Set INP_TYPE to VREF based differential receiver for SSTL, HSTL for single ended inputs.
        for reg_name in (('ddriob_data0'),
                         ('ddriob_data0','ddriob_data1'))[is_32]:
            ddriob_register_set.set_bitfields(reg_name,(('inp_type',1)),force,warn) # 1 - Vref based (sstl, hstl)        
# 6. Set INP_TYPE to Differential input receiver for differential inputs.
        for reg_name in (('ddriob_diff0'),
                         ('ddriob_diff0','ddriob_diff1'))[is_32]:
            ddriob_register_set.set_bitfields(reg_name,(('inp_type',2)),force,warn) # 2 - diff rcv        
# 7. Set TERM_EN to enabled for DDR3 and DDR2 bidirectional I/Os (Outputs and LPRDDR2 IOs are
#    un terminated).
        if is_DDR2 or is_DDR3:
            for reg_name in (('ddriob_data0','ddriob_diff0'),
                             ('ddriob_data0','ddriob_data1','ddriob_diff0','ddriob_diff1'))[is_32]:
                ddriob_register_set.set_bitfields(reg_name,(('term_en',1)),force,warn) 

# 8. Set DDRIOB_DATA1 and DDRIOB_DIFF1 registers to power down if only 16 bits of DQ DDR are
#     used (including ECC bits).
Andrey Filippov's avatar
Andrey Filippov committed
1468
## TODO: find out - what "power down" means - bit 0? or other bits that are already set according to bus width
1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517
# 9. For DDR2 and DDR3 – DCI only affects termination strength, so address and clock outputs do not
#     use DCI.
# 10. For LPDDR2 – DCI affects drive strength, so all I/Os use DCI.
# To enable internal VREF
            pass
# ° Set DDRIOB_DDR_CTRL.VREF_EXT_EN to 00 (disconnect I/Os from external signal)
        if is_int_vref:
            ddriob_register_set.set_bitfields('ddriob_ddr_ctrl', ('vref_ext_en',0),force,warn)        
# ° Set DDRIOB_DDR_CTRL.VREF_SEL to the appropriate voltage setting depending on the DDR
# standard (V REF=VCCO_DDR/2)
            if is_LPDDR2:
                vref_sel=1
            elif is_DDR3L:
                vref_sel=2
            elif is_DDR3_15:
                vref_sel=4
            elif is_DDR2:
                vref_sel=8
            else:
                print '***  Invalid memory type ***'
            ddriob_register_set.set_bitfields('ddriob_ddr_ctrl', ('vref_sel',vref_sel),force,warn)
# ° Set DDRIOB_DDR_CTRL.VREF_INT_EN to 1 to enable the internal VREF generator
            ddriob_register_set.set_bitfields('ddriob_ddr_ctrl', ('vref_int_en',1),force,warn)        
# To enable external VREF
        else: # if is_int_vref:
# ° Set DDRIOB_DDR_CTRL.VREF_INT_EN to 0 to disable the internal VREF generator
# ° Set DDRIOB_DDR_CTRL.VREF_SEL to 0000
# ° Set DDRIOB_DDR_CTRL.VREF_EXT_EN to 11 to connect the IOBs VREF input to the external
# pad for a 32-bit interface
# °Set DDRIOB_DDR_CTRL.VREF_EXT_EN to 01 to connect the IOBs VREF input to the external
# pad for a 16-bit interface
            ddriob_register_set.set_bitfields('ddriob_ddr_ctrl', (('vref_int_en',0),
                                                                  ('vref_sel',0),
                                                                  ('vref_ext_en',(1,3)[is_32])),force,warn)
#not in UG585, but used                    
            ddriob_register_set.set_bitfields('ddriob_ddr_ctrl', ('refio_en',1),force,warn)        
#configuring drive strength/slew rate. Seems to be the same for addr and clock, and DQ and DQS
        for reg_name in ('ddriob_drive_slew_addr','ddriob_drive_slew_clock'):
            ddriob_register_set.set_bitfields(reg_name,(
                                                        ('slew_n', self.features.get_par_value('OUT_SLEW_NEG')),
                                                        ('slew_p', self.features.get_par_value('OUT_SLEW_POS')),
                                                        ('drive_n',self.features.get_par_value('OUT_DRIVE_NEG')),
                                                        ('drive_p',self.features.get_par_value('OUT_DRIVE_POS'))),force,warn) # 0xd6861c        
        for reg_name in ('ddriob_drive_slew_data','ddriob_drive_slew_diff'):
            ddriob_register_set.set_bitfields(reg_name,(
                                                        ('slew_n', self.features.get_par_value('BIDIR_SLEW_NEG')),
                                                        ('slew_p', self.features.get_par_value('BIDIR_SLEW_POS')),
                                                        ('drive_n',self.features.get_par_value('BIDIR_DRIVE_NEG')),
                                                        ('drive_p',self.features.get_par_value('BIDIR_DRIVE_POS'))),force,warn) #0xf9861c
1518
  
1519
#TODO: Remove? 
1520 1521
            
    def parse_ddrc_raw_register_set(self,raw_configs,qualifier_char,force=True,warn=True):
1522
#        for i,attribs in enumerate(self.set_attribs):
1523
        for attribs in self.set_ddrc_attribs:
1524 1525 1526 1527 1528
            reg_set_name=attribs['NAME']
            reg_set= self.register_sets[reg_set_name]
            prefix= attribs['PREFIX']
            postfix= attribs['POSTFIX']
            reg_set.parse_options_set(raw_configs,prefix,postfix,self.postfixes,qualifier_char,force,warn) #force - readonly/undefined fields, warn: data does not fit in the bit field
1529 1530 1531
    def parse_ddriob_raw_register_set(self,raw_configs,qualifier_char,force=True,warn=True):
#        for i,attribs in enumerate(self.set_attribs):
        for attribs in self.set_ddriob_attribs:
1532 1533
            reg_set_name=attribs['NAME']
            reg_set= self.register_sets[reg_set_name]
1534 1535 1536 1537
            prefix= attribs['PREFIX']
            postfix= attribs['POSTFIX']
            reg_set.parse_options_set(raw_configs,prefix,postfix,self.postfixes,qualifier_char,force,warn) #force - readonly/undefined fields, warn: data does not fit in the bit field
    def print_ddrc_html_registers(self, html_file, show_bit_fields=True, show_comments=True,filter_fields=True):
1538 1539
        if not html_file:
            return
1540 1541 1542 1543 1544 1545 1546 1547
        for attribs in self.set_ddrc_attribs:
            reg_set_name=attribs['NAME']
            reg_set= self.ddrc_register_sets[reg_set_name]
            if len(reg_set.get_reg_names())>0:
                html_file.write('<h2>'+attribs['TITLE']+'</h2>\n')
                reg_set.print_html_registers(html_file, show_bit_fields, show_comments,filter_fields)
                html_file.write('<br/>\n')
    def print_ddriob_html_registers(self, html_file, show_bit_fields=True, show_comments=True,filter_fields=True):
1548 1549
        if not html_file:
            return
1550 1551 1552
        for attribs in self.set_ddrc_attribs:
            reg_set_name=attribs['NAME']
            reg_set= self.ddrc_register_sets[reg_set_name]
1553 1554
            if len(reg_set.get_reg_names())>0:
                html_file.write('<h2>'+attribs['TITLE']+'</h2>\n')
1555
                reg_set.print_html_registers(html_file, show_bit_fields, show_comments,filter_fields)
1556
                html_file.write('<br/>\n')
1557