mirror of https://github.com/openXC7/prjxray.git
238 lines
6.7 KiB
Python
Executable File
238 lines
6.7 KiB
Python
Executable File
#!/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()
|