Added first files
parent
fd6cffa55e
commit
792179779b
|
@ -0,0 +1,6 @@
|
|||
Litex System on Colorlight Board. ECP5 FPGA runs Risc-V Core and custom Hardware
|
||||
================================================================================
|
||||
|
||||
Board Image:
|
||||

|
||||
|
|
@ -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)
|
|
@ -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()
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 132 KiB |
Loading…
Reference in New Issue