| #!/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() |