Added first files

master
wolfgang 2020-09-24 22:29:48 +02:00
parent fd6cffa55e
commit 792179779b
4 changed files with 262 additions and 0 deletions

View File

@ -0,0 +1,6 @@
Litex System on Colorlight Board. ECP5 FPGA runs Risc-V Core and custom Hardware
================================================================================
Board Image:
![Board](doc/board.jpg)

150
bit_to_flash.py Executable file
View File

@ -0,0 +1,150 @@
#!/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)
print("IDCODE in bitstream is 0x%08x" % idcode)
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)

106
cl_full.py Executable file
View File

@ -0,0 +1,106 @@
#!/usr/bin/env python3
# This file is Copyright (c) 2020 Florent Kermarrec <florent@enjoy-digital.fr>
# License: BSD
import os
import argparse
from litex.soc.cores.clock import *
from litex.soc.cores.spi_flash import ECP5SPIFlash
from litex.soc.cores.gpio import GPIOOut, GPIOIn
from litex.soc.integration.soc_core import *
from litex.soc.integration.builder import *
from litex.build.lattice.trellis import trellis_args, trellis_argdict
from liteeth.phy.ecp5rgmii import LiteEthPHYRGMII
from litex.build.generic_platform import *
from litex_boards.targets import colorlight_5a_75x
_gpios = [
("gpio", 0, Pins("j4:1"), IOStandard("LVCMOS33")),
("gpio", 1, Pins("j4:5"), IOStandard("LVCMOS33")),
("j5", 0, Pins("j5:0"), IOStandard("LVCMOS33")),
("j5", 1, Pins("j5:1"), IOStandard("LVCMOS33")),
("j5", 2, Pins("j5:2"), IOStandard("LVCMOS33")),
("j5", 3, Pins("j5:4"), IOStandard("LVCMOS33")),
("j5", 4, Pins("j5:5"), IOStandard("LVCMOS33")),
("j5", 5, Pins("j5:6"), IOStandard("LVCMOS33")),
("j5", 6, Pins("j5:7"), IOStandard("LVCMOS33")),
("j5", 7, Pins("j5:8"), IOStandard("LVCMOS33")),
]
def load(file):
import os
os.system("mkdir -p prog")
print("--------")
f = open("prog/openocd.cfg", "w")
f.write(
"""
interface vsllink
adapter_khz 100
reset_config none
jtag newtap ecp5 tap -irlen 8 -expected-id 0x41111043
""")
f.close()
os.system(f"openocd -f prog/openocd.cfg -c \"transport select jtag; init; svf {file}; exit\"")
exit()
def main():
parser = argparse.ArgumentParser(description="LiteX SoC on Colorlight 5A-75X")
builder_args(parser)
soc_core_args(parser)
trellis_args(parser)
parser.add_argument("--build", action="store_true", help="Build bitstream")
parser.add_argument("--load", action="store_true", help="Load bitstream")
parser.add_argument("--flash", action="store_true", help="Load bitstream to flash")
parser.add_argument("--use-internal-osc", action="store_true", help="Use internal oscillator")
parser.add_argument("--sdram-rate", default="1:1", help="SDRAM Rate 1:1 Full Rate (default), 1:2 Half Rate")
parser.set_defaults(uart_name='crossover', no_uart=False, cpu_type="vexriscv")
args = parser.parse_args()
soc = colorlight_5a_75x.BaseSoC(board="5a-75b", revision="7.0",
sys_clk_freq = 80e6,
use_internal_osc = args.use_internal_osc,
sdram_rate = args.sdram_rate,
**soc_core_argdict(args))
soc.platform.name ="clFull"
# 32MBit SPIFlash ---------------------------------------------------------------------------------
soc.mem_map["spiflash"] = 0xc0000000
# Boot at +1MB
soc.add_constant("FLASH_BOOT_ADDRESS", soc.mem_map["spiflash"] + 1024*1024)
soc.add_spi_flash(name="spiflash", mode="1x", dummy_cycles=8, clk_freq=5e6)
soc.submodules.ethphy = LiteEthPHYRGMII(
clock_pads=soc.platform.request("eth_clocks", 0),
pads=soc.platform.request("eth", 0))
soc.add_csr("ethphy")
soc.add_etherbone(name="etherbone", phy=soc.ethphy,
mac_address=0x10e2d5000000,
ip_address="10.42.1.222",
udp_port=1234)
soc.submodules.led = GPIOOut(soc.platform.request("user_led_n"))
soc.add_csr("led")
builder = Builder(soc, output_dir="build", csr_csv="scripts/csr.csv")
builder.build(**trellis_argdict(args), run=args.build)
if args.flash: # Convert Bit File to Jtag Write Flash command
name = os.path.join(builder.gateware_dir, soc.build_name)
os.system(f"./bit_to_flash.py {name}.bit {name}.svf.flash")
load(name + ".svf.flash")
return
if args.load: # Temporary Load into FPGA
load(os.path.join(builder.gateware_dir, soc.build_name + ".svf"))
if __name__ == "__main__":
main()

BIN
doc/board.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB