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:
Florent Kermarrec 2020-04-14 16:14:18 +02:00
parent 4b4f2f9eb8
commit cb95962850
5 changed files with 25 additions and 228 deletions

View file

@ -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.

View file

@ -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.

View file

@ -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)

View file

@ -20,6 +20,16 @@
# 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.
#
# 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
# Etherbone stack that need to be optimized. It was initially just used to validate the reversed
# pinout but happens to work on hardware...
@ -75,7 +85,6 @@ class _CRG(Module):
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_48, 48e6, margin=0)
#self.comb += self.cd_usb_48.clk.eq(self.cd_sys.clk)
# SDRAM clock
self.specials += DDROutput(1, 0, platform.request("sdram_clock"), ClockSignal("sys_ps"))
@ -127,44 +136,23 @@ class BaseSoC(SoCCore):
# Load ---------------------------------------------------------------------------------------------
def openocd_run_svf(filename, iface="ftdi"):
def load():
import os
f = open("openocd.cfg", "w")
if (iface == "ftdi"):
f.write(
"""adapter driver ftdi
f.write(
"""
interface ftdi
ftdi_vid_pid 0x0403 0x6011
ftdi_channel 0
ftdi_layout_init 0x0098 0x008b
reset_config none
adapter speed 25000
adapter_khz 25000
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()
os.system("openocd -d0 -f openocd.cfg -c \"transport select jtag; init; svf -tap lfe5u25.tap {} -quiet -progress; exit\"".format(filename))
os.system("rm openocd.cfg")
os.system("openocd -f openocd.cfg -c \"transport select jtag; init; svf soc_basesoc_colorlight_5a_75b/gateware/top.svf; 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 --------------------------------------------------------------------------------------------
def main():
@ -177,18 +165,11 @@ def main():
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("--load", action="store_true", help="load bitstream")
parser.add_argument("--flash", action="store_true", help="flash bitstream")
parser.add_argument("--iface", default="ftdi", help="loading jtag interface")
parser.add_argument("--sys-clk-freq", default=60e6,
help="system clock frequency (default=60MHz)")
parser.add_argument("--sys-clk-freq", default=60e6, help="system clock frequency (default=60MHz)")
args = parser.parse_args()
if args.load:
load(iface=args.iface)
if args.flash:
flash(iface=args.iface)
load()
assert not (args.with_ethernet and args.with_etherbone)
soc = BaseSoC(revision=args.revision,

View file

@ -42,16 +42,18 @@ class _CRG(Module):
self.submodules.pll = pll = ECP5PLL()
self.comb += pll.reset.eq(rst)
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)
self.specials += AsyncResetSynchronizer(self.cd_sys, ~pll.locked | rst)
# 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_48 = ClockDomain()
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_12, 12e6, margin=0)
usb_pll.create_clkout(self.cd_usb_48, 48e6, margin=0)
# SDRAM clock
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")
parser.add_argument("--device", dest="device", default="LFE5U-45F",
help="FPGA device, ULX3S can be populated with LFE5U-45F (default) or LFE5U-85F")
parser.add_argument("--sys-clk-freq", default=48e6,
help="system clock frequency (default=48MHz)")
parser.add_argument("--sys-clk-freq", default=50e6,
help="system clock frequency (default=50MHz)")
parser.add_argument("--sdram-module", default="MT48LC16M16",
help="SDRAM module: MT48LC16M16, AS4C32M16 or AS4C16M16 (default=MT48LC16M16)")
builder_args(parser)