#!/usr/bin/env python3 # -*- coding: utf-8 -*- # # Copyright (C) 2017-2020 The Project X-Ray Authors. # # Use of this source code is governed by a ISC-style # license that can be found in the LICENSE file or at # https://opensource.org/licenses/ISC # # SPDX-License-Identifier: ISC import sys import time import argparse from litex import RemoteClient from sdram_init import * def identify_fpga(wb): """ Gets the FPGA identifier and prints it on terminal.""" fpga_id = "" for i in range(256): c = chr(wb.read(wb.bases.identifier_mem + 4 * i) & 0xff) fpga_id += c if c == "\0": break print(fpga_id) def seed_to_data(seed, random=True): if random: return (1664525 * seed + 1013904223) & 0xffffffff else: return seed def write_pattern(wb, length): for i in range(length): wb.write(wb.mems.main_ram.base + 4 * i, seed_to_data(i)) def check_pattern(wb, length, debug=False): errors = 0 for i in range(length): error = 0 if wb.read(wb.mems.main_ram.base + 4 * i) != seed_to_data(i): error = 1 if debug: print( "{}: 0x{:08x}, 0x{:08x} KO".format( i, wb.read(wb.mems.main_ram.base + 4 * i), seed_to_data(i))) else: if debug: print( "{}: 0x{:08x}, 0x{:08x} OK".format( i, wb.read(wb.mems.main_ram.base + 4 * i), seed_to_data(i))) errors += error return errors def find_bitslips_delays(wb): """ Finds bitslip and delay values that can be used with the implemented DDR design.""" nbitslips = 8 ndelays = 32 nmodules = 2 nwords = 16 final_bitslip = None final_delay = None for bitslip in range(nbitslips): print("bitslip {:d}: |".format(bitslip), end="") for delay in range(ndelays): for module in range(nmodules): wb.regs.ddrphy_dly_sel.write(1 << module) wb.regs.ddrphy_rdly_dq_rst.write(1) wb.regs.ddrphy_rdly_dq_bitslip_rst.write(1) for i in range(bitslip): wb.regs.ddrphy_rdly_dq_bitslip.write(1) for i in range(delay): wb.regs.ddrphy_rdly_dq_inc.write(1) write_pattern(wb, nwords) errors = check_pattern(wb, nwords) if errors: print("..|", end="") else: print("{:02d}|".format(delay), end="") final_bitslip = bitslip if final_bitslip is None else final_bitslip final_delay = delay if final_delay is None else final_delay sys.stdout.flush() print("") assert final_bitslip is not None and final_delay is not None, "bitslip/delay values not found" return final_bitslip, final_delay def set_bitslip_delay(wb, bitslip, delay): """ Sets bitslip and delay values.""" nmodules = 2 for module in range(nmodules): wb.regs.ddrphy_dly_sel.write(1 << module) wb.regs.ddrphy_rdly_dq_rst.write(1) wb.regs.ddrphy_rdly_dq_bitslip_rst.write(1) for i in range(bitslip): wb.regs.ddrphy_rdly_dq_bitslip.write(1) for i in range(delay): wb.regs.ddrphy_rdly_dq_inc.write(1) def read_word_offset(read_only=False): word = None if not read_only: print("\n==================================================\n") print( "Set a byte long word to write to memory (e.g. 0xdeadbeef): ", end="") word = int(input(), 16) & 0xffffffff print("\n==================================================\n") print("Set offset from base memory address: ", end="") offset = int(input()) print("\n==================================================\n") print("Set number of words to read or write: ", end="") length = int(input()) return word, offset, length def write_user_pattern(wb, offset, length, pattern): for i in range(length): wb.write(wb.mems.main_ram.base + 4 * (offset + i), pattern) def read_user_pattern(wb, offset, length, pattern=None): for i in range(length): read_value = wb.read(wb.mems.main_ram.base + 4 * (offset + i)) if pattern is None: print("0x{:08x}".format(read_value)) else: if read_value == pattern: outcome = "CORRECT" else: outcome = "INCORRECT" print( "{} --> 0x{:08x}, 0x{:08x}".format( outcome, read_value, pattern)) def start_command_interface(wb): cmd_list = """ Commands list: 0 --> Write memory 1 --> Read memory 2 --> Write/Read memory 3 --> Print commands list 4 --> Exit """ print(cmd_list) while True: print("\nWaiting for command: ", end="") cmd = int(input()) if cmd == 0: word, offset, length = read_word_offset() write_user_pattern(wb, offset, length, word) elif cmd == 1: word, offset, length = read_word_offset(True) read_user_pattern(wb, offset, length) elif cmd == 2: word, offset, length = read_word_offset() write_user_pattern(wb, offset, length, word) read_user_pattern(wb, offset, length, word) elif cmd == 3: print(cmd_list) elif cmd == 4: break else: print("Command not recognized, try again...") def main(): parser = argparse.ArgumentParser( description="Script to test correct DDR behaviour.") parser.add_argument( '--bitslip', default=None, help="Defines a bitslip value.") parser.add_argument('--delay', default=None, help="Defines a delay value.") args = parser.parse_args() wb = RemoteClient(debug=False) wb.open() # software control wb.regs.sdram_dfii_control.write(0) # sdram initialization for i, (comment, a, ba, cmd, delay) in enumerate(init_sequence): print(comment) wb.regs.sdram_dfii_pi0_address.write(a) wb.regs.sdram_dfii_pi0_baddress.write(ba) if i < 2: wb.regs.sdram_dfii_control.write(cmd) else: wb.regs.sdram_dfii_pi0_command.write(cmd) wb.regs.sdram_dfii_pi0_command_issue.write(1) # hardware control wb.regs.sdram_dfii_control.write(dfii_control_sel) if args.bitslip is None or args.delay is None: bitslip, delay = find_bitslips_delays(wb) else: bitslip = int(args.bitslip) delay = int(args.delay) set_bitslip_delay(wb, bitslip, delay) start_command_interface(wb) wb.close() if __name__ == "__main__": main()