mirror of
https://github.com/litex-hub/litex-boards.git
synced 2025-01-03 03:43:36 -05:00
targets/ulx3s and colorlight_5a_75b: cleanup USB ACM addition and only keep USB ACM changes.
- remove update in loading/flashing: we need to thinks how to integrate this. - remove specific README: documentation is moved to the files, link to more complete project can be added if maintained externally, as done for the iCEBreaker for example. - revert default freq on ULX3S to 50MHz and instantiate a second PLL as done on the colorlight.
This commit is contained in:
parent
4b4f2f9eb8
commit
cb95962850
5 changed files with 25 additions and 228 deletions
|
@ -1,26 +0,0 @@
|
||||||
USB
|
|
||||||
===
|
|
||||||
USB support has been integrated for the V7.0 this board. Supporting other
|
|
||||||
versions should be trivial and just need pinning changes. To build with
|
|
||||||
usb support just do;
|
|
||||||
|
|
||||||
./colourlight_5a_75b.py --uart-name=usb_cdc
|
|
||||||
|
|
||||||
To install onto the board;
|
|
||||||
|
|
||||||
./colourlight_5a_75b.py --load
|
|
||||||
|
|
||||||
The USB Serial connection will appear as /dev/ttyACMx, or equivalent on your OS.
|
|
||||||
|
|
||||||
Pinning for V7.0;
|
|
||||||
|
|
||||||
* Replace U23 with a SN74CBT3245APWR, or remove U23 and place jumper wires.
|
|
||||||
(You're basically making the ports Bi-directional).
|
|
||||||
|
|
||||||
* Place a 15K resistor between J4 pin 2 and J4 pin 4.
|
|
||||||
|
|
||||||
* Place a 15K resistor between J4 pin 3 and J4 pin 4.
|
|
||||||
|
|
||||||
* Place a 1.5K resistor between J4 pin 1 and J4 pin 3.
|
|
||||||
|
|
||||||
* Connect USB DP (Green) to J4 pin 3, USB DN (White) to J4 pin 2.
|
|
|
@ -1,11 +0,0 @@
|
||||||
USB
|
|
||||||
===
|
|
||||||
USB support has been integrated and tested for V3.0.3 this board. Revisions
|
|
||||||
higher than this should be supported. The USB connection is on US2.
|
|
||||||
|
|
||||||
To build with usb support just do;
|
|
||||||
|
|
||||||
./ulx3s.py --uart-name=usb_cdc
|
|
||||||
|
|
||||||
The USB Serial connection will appear as /dev/ttyACMx, or equivalent on your OS.
|
|
||||||
|
|
|
@ -1,149 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import textwrap
|
|
||||||
|
|
||||||
# Very basic bitstream to SVF converter, tested with the ULX3S WiFi interface
|
|
||||||
|
|
||||||
flash_page_size = 256
|
|
||||||
erase_block_size = 64*1024
|
|
||||||
|
|
||||||
|
|
||||||
def bitreverse(x):
|
|
||||||
y = 0
|
|
||||||
for i in range(8):
|
|
||||||
if (x >> (7 - i)) & 1 == 1:
|
|
||||||
y |= (1 << i)
|
|
||||||
return y
|
|
||||||
|
|
||||||
with open(sys.argv[1], 'rb') as bitf:
|
|
||||||
bs = bitf.read()
|
|
||||||
# Autodetect IDCODE from bitstream
|
|
||||||
idcode_cmd = bytes([0xE2, 0x00, 0x00, 0x00])
|
|
||||||
idcode = None
|
|
||||||
for i in range(len(bs) - 4):
|
|
||||||
if bs[i:i+4] == idcode_cmd:
|
|
||||||
idcode = bs[i+4] << 24
|
|
||||||
idcode |= bs[i+5] << 16
|
|
||||||
idcode |= bs[i+6] << 8
|
|
||||||
idcode |= bs[i+7]
|
|
||||||
break
|
|
||||||
if idcode is None:
|
|
||||||
print("Failed to find IDCODE in bitstream, check bitstream is valid")
|
|
||||||
sys.exit(1)
|
|
||||||
bitf.seek(0)
|
|
||||||
|
|
||||||
address = 0
|
|
||||||
last_page = -1
|
|
||||||
|
|
||||||
with open(sys.argv[2], 'w') as svf:
|
|
||||||
print("""
|
|
||||||
STATE RESET;
|
|
||||||
HDR 0;
|
|
||||||
HIR 0;
|
|
||||||
TDR 0;
|
|
||||||
TIR 0;
|
|
||||||
ENDDR DRPAUSE;
|
|
||||||
ENDIR IRPAUSE;
|
|
||||||
STATE IDLE;
|
|
||||||
""", file=svf)
|
|
||||||
print("""
|
|
||||||
SIR 8 TDI (E0);
|
|
||||||
SDR 32 TDI (00000000)
|
|
||||||
TDO ({:08X})
|
|
||||||
MASK (FFFFFFFF);
|
|
||||||
""".format(idcode), file=svf)
|
|
||||||
print("""
|
|
||||||
SIR 8 TDI (1C);
|
|
||||||
SDR 510 TDI (3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
|
|
||||||
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
|
|
||||||
|
|
||||||
// Enter Programming mode
|
|
||||||
SIR 8 TDI (C6);
|
|
||||||
SDR 8 TDI (00);
|
|
||||||
RUNTEST IDLE 2 TCK 1.00E-02 SEC;
|
|
||||||
|
|
||||||
// Erase
|
|
||||||
SIR 8 TDI (0E);
|
|
||||||
SDR 8 TDI (01);
|
|
||||||
RUNTEST IDLE 2 TCK 2.0E-1 SEC;
|
|
||||||
|
|
||||||
// Read STATUS
|
|
||||||
SIR 8 TDI (3C);
|
|
||||||
SDR 32 TDI (00000000)
|
|
||||||
TDO (00000000)
|
|
||||||
MASK (0000B000);
|
|
||||||
|
|
||||||
// Exit Programming mode
|
|
||||||
SIR 8 TDI (26);
|
|
||||||
RUNTEST IDLE 2 TCK 1.00E-02 SEC;
|
|
||||||
|
|
||||||
// BYPASS
|
|
||||||
SIR 8 TDI (FF);
|
|
||||||
STATE IDLE;
|
|
||||||
RUNTEST 32 TCK;
|
|
||||||
RUNTEST 2.00E-2 SEC;
|
|
||||||
|
|
||||||
// Enter SPI mode
|
|
||||||
|
|
||||||
SIR 8 TDI (3A);
|
|
||||||
SDR 16 TDI (68FE);
|
|
||||||
STATE IDLE;
|
|
||||||
RUNTEST 32 TCK;
|
|
||||||
RUNTEST 2.00E-2 SEC;
|
|
||||||
|
|
||||||
// SPI IO
|
|
||||||
SDR 8 TDI (D5);
|
|
||||||
|
|
||||||
RUNTEST 2.00E-0 SEC;
|
|
||||||
|
|
||||||
// CONFIRM FLASH ID
|
|
||||||
SDR 32 TDI (000000F9)
|
|
||||||
TDO (68FFFFFF)
|
|
||||||
MASK (FF000000);
|
|
||||||
|
|
||||||
SDR 8 TDI(60);
|
|
||||||
SDR 16 TDI(0080);
|
|
||||||
RUNTEST 1.00E-0 SEC;
|
|
||||||
|
|
||||||
|
|
||||||
""", file=svf)
|
|
||||||
while True:
|
|
||||||
if((address // 0x10000) != last_page):
|
|
||||||
last_page = (address // 0x10000)
|
|
||||||
print("""SDR 8 TDI (60);
|
|
||||||
""", file=svf)
|
|
||||||
address_flipped = [bitreverse(x) for x in [0xd8,int(address // 0x10000),0x00,0x00]]
|
|
||||||
hex_address= ["{:02X}".format(x) for x in reversed(address_flipped)]
|
|
||||||
print("\n".join(textwrap.wrap("SDR {} TDI ({});".format(8*len(hex_address), "".join(hex_address)), 100)), file=svf)
|
|
||||||
print("""RUNTEST 3.00 SEC;
|
|
||||||
""", file=svf)
|
|
||||||
|
|
||||||
chunk = bitf.read(flash_page_size)
|
|
||||||
if not chunk:
|
|
||||||
break
|
|
||||||
# Convert chunk to bit-reversed hex
|
|
||||||
br_chunk = [bitreverse(x) for x in bytes([0x02, int(address / 0x10000 % 0x100),int(address / 0x100 % 0x100),int(address % 0x100)]) + chunk]
|
|
||||||
address += len(chunk)
|
|
||||||
hex_chunk = ["{:02X}".format(x) for x in reversed(br_chunk)]
|
|
||||||
print("""
|
|
||||||
SDR 8 TDI (60);
|
|
||||||
""", file=svf)
|
|
||||||
print("\n".join(textwrap.wrap("SDR {} TDI ({});".format(8*len(br_chunk), "".join(hex_chunk)), 100)), file=svf)
|
|
||||||
print("""
|
|
||||||
RUNTEST 2.50E-2 SEC;
|
|
||||||
""", file=svf)
|
|
||||||
|
|
||||||
print("""
|
|
||||||
// BYPASS
|
|
||||||
SIR 8 TDI (FF);
|
|
||||||
|
|
||||||
//REFRESH
|
|
||||||
SIR 8 TDI(79);
|
|
||||||
SDR 24 TDI(000000);
|
|
||||||
|
|
||||||
STATE IDLE;
|
|
||||||
RUNTEST 32 TCK;
|
|
||||||
RUNTEST 2.00E-2 SEC;
|
|
||||||
STATE RESET;
|
|
||||||
""", file=svf)
|
|
|
@ -20,6 +20,16 @@
|
||||||
# wishbone-tool --ethernet-host 192.168.1.50 --server terminal --csr-csv csr.csv
|
# wishbone-tool --ethernet-host 192.168.1.50 --server terminal --csr-csv csr.csv
|
||||||
# You should see the LiteX BIOS and be able to interact with it.
|
# You should see the LiteX BIOS and be able to interact with it.
|
||||||
#
|
#
|
||||||
|
# 3) SoC with USB-ACM UART (on V7.0):
|
||||||
|
# - Replace U23 with a SN74CBT3245APWR or remove U23 and place jumper wires to make the ports bi-directional.
|
||||||
|
# - Place a 15K resistor between J4 pin 2 and J4 pin 4.
|
||||||
|
# - Place a 15K resistor between J4 pin 3 and J4 pin 4.
|
||||||
|
# - Place a 1.5K resistor between J4 pin 1 and J4 pin 3.
|
||||||
|
# - Connect USB DP (Green) to J4 pin 3, USB DN (White) to J4 pin 2.
|
||||||
|
# ./colorlight_5a_75b.py --revision=7.0 --uart-name=usb_cdcc
|
||||||
|
# ./colorlight_5a_75b.py --load
|
||||||
|
# You should see the LiteX BIOS and be able to interact with it.
|
||||||
|
#
|
||||||
# Disclaimer: SoC 2) is still a Proof of Concept with large timings violations on the IP/UDP and
|
# Disclaimer: SoC 2) is still a Proof of Concept with large timings violations on the IP/UDP and
|
||||||
# Etherbone stack that need to be optimized. It was initially just used to validate the reversed
|
# Etherbone stack that need to be optimized. It was initially just used to validate the reversed
|
||||||
# pinout but happens to work on hardware...
|
# pinout but happens to work on hardware...
|
||||||
|
@ -75,7 +85,6 @@ class _CRG(Module):
|
||||||
self.clock_domains.cd_usb_48 = ClockDomain()
|
self.clock_domains.cd_usb_48 = ClockDomain()
|
||||||
usb_pll.create_clkout(self.cd_usb_12, 12e6, margin=0)
|
usb_pll.create_clkout(self.cd_usb_12, 12e6, margin=0)
|
||||||
usb_pll.create_clkout(self.cd_usb_48, 48e6, margin=0)
|
usb_pll.create_clkout(self.cd_usb_48, 48e6, margin=0)
|
||||||
#self.comb += self.cd_usb_48.clk.eq(self.cd_sys.clk)
|
|
||||||
|
|
||||||
# SDRAM clock
|
# SDRAM clock
|
||||||
self.specials += DDROutput(1, 0, platform.request("sdram_clock"), ClockSignal("sys_ps"))
|
self.specials += DDROutput(1, 0, platform.request("sdram_clock"), ClockSignal("sys_ps"))
|
||||||
|
@ -127,44 +136,23 @@ class BaseSoC(SoCCore):
|
||||||
|
|
||||||
# Load ---------------------------------------------------------------------------------------------
|
# Load ---------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
def openocd_run_svf(filename, iface="ftdi"):
|
def load():
|
||||||
import os
|
import os
|
||||||
f = open("openocd.cfg", "w")
|
f = open("openocd.cfg", "w")
|
||||||
if (iface == "ftdi"):
|
f.write(
|
||||||
f.write(
|
"""
|
||||||
"""adapter driver ftdi
|
interface ftdi
|
||||||
ftdi_vid_pid 0x0403 0x6011
|
ftdi_vid_pid 0x0403 0x6011
|
||||||
ftdi_channel 0
|
ftdi_channel 0
|
||||||
ftdi_layout_init 0x0098 0x008b
|
ftdi_layout_init 0x0098 0x008b
|
||||||
reset_config none
|
reset_config none
|
||||||
adapter speed 25000
|
adapter_khz 25000
|
||||||
jtag newtap ecp5 tap -irlen 8 -expected-id 0x41111043
|
jtag newtap ecp5 tap -irlen 8 -expected-id 0x41111043
|
||||||
""")
|
""")
|
||||||
elif (iface=="jlink"):
|
|
||||||
f.write("""adapter driver jlink
|
|
||||||
transport select jtag
|
|
||||||
reset_config none
|
|
||||||
telnet_port 4444
|
|
||||||
adapter speed 10000
|
|
||||||
jtag newtap lfe5u25 tap -irlen 8 -irmask 0xFF -ircapture 0x5 -expected-id 0x41111043
|
|
||||||
""")
|
|
||||||
else:
|
|
||||||
print("Unrecognised jtag interface")
|
|
||||||
exit()
|
|
||||||
|
|
||||||
f.close()
|
f.close()
|
||||||
os.system("openocd -d0 -f openocd.cfg -c \"transport select jtag; init; svf -tap lfe5u25.tap {} -quiet -progress; exit\"".format(filename))
|
os.system("openocd -f openocd.cfg -c \"transport select jtag; init; svf soc_basesoc_colorlight_5a_75b/gateware/top.svf; exit\"")
|
||||||
os.system("rm openocd.cfg")
|
|
||||||
exit()
|
exit()
|
||||||
|
|
||||||
def load(iface="ftdi"):
|
|
||||||
openocd_run_svf("soc_basesoc_colorlight_5a_75b/gateware/top.svf",iface=iface)
|
|
||||||
|
|
||||||
def flash(iface="ftdi"):
|
|
||||||
import os
|
|
||||||
os.system("./bit_to_flash.py soc_basesoc_colorlight_5a_75b/gateware/top.bit soc_basesoc_colorlight_5a_75b/gateware/top.svf.flash")
|
|
||||||
openocd_run_svf("soc_basesoc_colorlight_5a_75b/gateware/top.svf.flash",iface=iface)
|
|
||||||
|
|
||||||
# Build --------------------------------------------------------------------------------------------
|
# Build --------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
@ -177,18 +165,11 @@ def main():
|
||||||
parser.add_argument("--with-etherbone", action="store_true", help="enable Etherbone support")
|
parser.add_argument("--with-etherbone", action="store_true", help="enable Etherbone support")
|
||||||
parser.add_argument("--eth-phy", default=0, type=int, help="Ethernet PHY 0 or 1 (default=0)")
|
parser.add_argument("--eth-phy", default=0, type=int, help="Ethernet PHY 0 or 1 (default=0)")
|
||||||
parser.add_argument("--load", action="store_true", help="load bitstream")
|
parser.add_argument("--load", action="store_true", help="load bitstream")
|
||||||
parser.add_argument("--flash", action="store_true", help="flash bitstream")
|
parser.add_argument("--sys-clk-freq", default=60e6, help="system clock frequency (default=60MHz)")
|
||||||
parser.add_argument("--iface", default="ftdi", help="loading jtag interface")
|
|
||||||
parser.add_argument("--sys-clk-freq", default=60e6,
|
|
||||||
help="system clock frequency (default=60MHz)")
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
if args.load:
|
if args.load:
|
||||||
load(iface=args.iface)
|
load()
|
||||||
|
|
||||||
if args.flash:
|
|
||||||
flash(iface=args.iface)
|
|
||||||
|
|
||||||
assert not (args.with_ethernet and args.with_etherbone)
|
assert not (args.with_ethernet and args.with_etherbone)
|
||||||
soc = BaseSoC(revision=args.revision,
|
soc = BaseSoC(revision=args.revision,
|
||||||
|
|
|
@ -42,16 +42,18 @@ class _CRG(Module):
|
||||||
self.submodules.pll = pll = ECP5PLL()
|
self.submodules.pll = pll = ECP5PLL()
|
||||||
self.comb += pll.reset.eq(rst)
|
self.comb += pll.reset.eq(rst)
|
||||||
pll.register_clkin(clk25, 25e6)
|
pll.register_clkin(clk25, 25e6)
|
||||||
pll.create_clkout(self.cd_sys, sys_clk_freq, margin=0)
|
pll.create_clkout(self.cd_sys, sys_clk_freq)
|
||||||
pll.create_clkout(self.cd_sys_ps, sys_clk_freq, phase=90)
|
pll.create_clkout(self.cd_sys_ps, sys_clk_freq, phase=90)
|
||||||
self.specials += AsyncResetSynchronizer(self.cd_sys, ~pll.locked | rst)
|
self.specials += AsyncResetSynchronizer(self.cd_sys, ~pll.locked | rst)
|
||||||
|
|
||||||
# USB PLL
|
# USB PLL
|
||||||
if with_usb_pll:
|
if with_usb_pll:
|
||||||
|
self.submodules.usb_pll = usb_pll = ECP5PLL()
|
||||||
|
usb_pll.register_clkin(clk25, 25e6)
|
||||||
self.clock_domains.cd_usb_12 = ClockDomain()
|
self.clock_domains.cd_usb_12 = ClockDomain()
|
||||||
self.clock_domains.cd_usb_48 = ClockDomain()
|
self.clock_domains.cd_usb_48 = ClockDomain()
|
||||||
pll.create_clkout(self.cd_usb_12, 12e6, margin=0)
|
usb_pll.create_clkout(self.cd_usb_12, 12e6, margin=0)
|
||||||
self.comb += self.cd_usb_48.clk.eq(self.cd_sys.clk)
|
usb_pll.create_clkout(self.cd_usb_48, 48e6, margin=0)
|
||||||
|
|
||||||
# SDRAM clock
|
# SDRAM clock
|
||||||
self.specials += DDROutput(1, 0, platform.request("sdram_clock"), ClockSignal("sys_ps"))
|
self.specials += DDROutput(1, 0, platform.request("sdram_clock"), ClockSignal("sys_ps"))
|
||||||
|
@ -95,8 +97,8 @@ def main():
|
||||||
help="gateware toolchain to use, trellis (default) or diamond")
|
help="gateware toolchain to use, trellis (default) or diamond")
|
||||||
parser.add_argument("--device", dest="device", default="LFE5U-45F",
|
parser.add_argument("--device", dest="device", default="LFE5U-45F",
|
||||||
help="FPGA device, ULX3S can be populated with LFE5U-45F (default) or LFE5U-85F")
|
help="FPGA device, ULX3S can be populated with LFE5U-45F (default) or LFE5U-85F")
|
||||||
parser.add_argument("--sys-clk-freq", default=48e6,
|
parser.add_argument("--sys-clk-freq", default=50e6,
|
||||||
help="system clock frequency (default=48MHz)")
|
help="system clock frequency (default=50MHz)")
|
||||||
parser.add_argument("--sdram-module", default="MT48LC16M16",
|
parser.add_argument("--sdram-module", default="MT48LC16M16",
|
||||||
help="SDRAM module: MT48LC16M16, AS4C32M16 or AS4C16M16 (default=MT48LC16M16)")
|
help="SDRAM module: MT48LC16M16, AS4C32M16 or AS4C16M16 (default=MT48LC16M16)")
|
||||||
builder_args(parser)
|
builder_args(parser)
|
||||||
|
|
Loading…
Reference in a new issue