From fb5a88a6b80427b07dcf97923735a819eea16e1f Mon Sep 17 00:00:00 2001 From: Alessandro Comodi Date: Mon, 10 Feb 2020 14:35:37 +0100 Subject: [PATCH] uart_ddr: improve sdram test script Signed-off-by: Alessandro Comodi --- .../litex/uart_ddr/arty/scripts/test_sdram.py | 237 +++++++++++++----- 1 file changed, 181 insertions(+), 56 deletions(-) diff --git a/minitests/litex/uart_ddr/arty/scripts/test_sdram.py b/minitests/litex/uart_ddr/arty/scripts/test_sdram.py index acee9d18..be8ac057 100755 --- a/minitests/litex/uart_ddr/arty/scripts/test_sdram.py +++ b/minitests/litex/uart_ddr/arty/scripts/test_sdram.py @@ -2,41 +2,22 @@ import sys import time +import argparse from litex import RemoteClient from sdram_init import * -wb = RemoteClient(debug=False) -wb.open() -# # # - -# get identifier -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) - -# 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) +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): @@ -46,12 +27,12 @@ def seed_to_data(seed, random=True): return seed -def write_pattern(length): +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(length, debug=False): +def check_pattern(wb, length, debug=False): errors = 0 for i in range(length): error = 0 @@ -72,32 +53,176 @@ def check_pattern(length, debug=False): return errors -# find working bitslips and delays -nbitslips = 8 -ndelays = 32 -nmodules = 2 -nwords = 16 +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 -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(nwords) - errors = check_pattern(nwords) - if errors: - print("..|", end="") + 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: - print("{:02d}|".format(delay), end="") - sys.stdout.flush() - print("") + if read_value == pattern: + outcome = "CORRECT" + else: + outcome = "INCORRECT" -# # # + print( + "{} --> 0x{:08x}, 0x{:08x}".format( + outcome, read_value, pattern)) -wb.close() + +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()