Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sipeed Tang Nano 1k support #518

Open
Podolyakofs opened this issue Aug 7, 2023 · 2 comments
Open

Sipeed Tang Nano 1k support #518

Podolyakofs opened this issue Aug 7, 2023 · 2 comments

Comments

@Podolyakofs
Copy link

Good day,
I have Sipeed Tang Nano 1K (which is replacement for Tang Nano already supported in Litex) with GW1NZ-LV1QN48C6/I5 and BL702 usb-jtag

Here's its documentation https://wiki.sipeed.com/hardware/en/tang/Tang-Nano-1K/Nano-1k.html

Looks like to run Litex on it previous sipeed_tang_nano board definitions need some changes:

sipeed_tang_nano_1k_platform.py
from migen import *

from litex.build.generic_platform import *
from litex.build.gowin.platform import GowinPlatform
from litex.build.openfpgaloader import OpenFPGALoader
from litex.build.gowin.programmer import GowinProgrammer

# IOs ----------------------------------------------------------------------------------------------

_io = [   #All io changes
    # Clk / Rst
    ("clk27",  0, Pins("47"), IOStandard("LVCMOS33"),Misc("PULL_MODE=UP")),

    ("rst_n",  0, Pins("13"), IOStandard("LVCMOS33"),Misc("PULL_MODE=UP")),

    # Leds
    ("user_led", 0, Pins("9"), IOStandard("LVCMOS33"), Misc("PULL_MODE=UP")),
    ("user_led", 1, Pins("10"), IOStandard("LVCMOS33"),Misc("PULL_MODE=UP")),
    ("user_led", 2, Pins("11"), IOStandard("LVCMOS33"),Misc("PULL_MODE=UP")),

    # Buttons.
    ("user_btn", 0, Pins("44"),  IOStandard("LVCMOS33")),
    ("user_btn", 1, Pins("13"),  IOStandard("LVCMOS33")),

    # Serial
    # ("serial", 0,    #Can use other pins, this on this board used for led, disabled for now
    #     Subsignal("tx", Pins("8")), 
    #     Subsignal("rx", Pins("9")),
    #     IOStandard("LVCMOS33")
    # ),
]

# Connectors ---------------------------------------------------------------------------------------

_connectors = []

# Platform -----------------------------------------------------------------------------------------

class Platform(GowinPlatform):
    default_clk_name   = "clk27"  #Change freq to 27 Mhz
    default_clk_period = 1e9/27e6 #Change freq

    def __init__(self, toolchain="gowin"):
        GowinPlatform.__init__(self, "GW1NZ-LV1QN48C6/I5", _io, _connectors, toolchain=toolchain, devicename="GW1NZ-1") #Change FPGA name 
        self.toolchain.options["use_done_as_gpio"]      = 1
        self.toolchain.options["use_reconfign_as_gpio"] = 1

    def create_programmer(self, kit="openfpgaloader"):
        if kit == "gowin":
            return GowinProgrammer(self.devicename)
        else: 
            return OpenFPGALoader(cable="ft2232") #Change to BL702 support
        
    def do_finalize(self, fragment):
        GowinPlatform.do_finalize(self, fragment)
        self.add_period_constraint(self.lookup_request("clk27", loose=True), 1e9/27e6) #Change freq


 
sipeed_tang_nano_1k_platform.py
from migen import *

from litex.gen import *

import stn_1k_platform as sipeed_tang_nano

from gowin_gw1n import  GW1NPLL  #We need some changes to  "from litex.soc.cores.clock.gowin_gw1n import GW1NPLL"
from litex.soc.integration.soc_core import *
from litex.soc.integration.builder import *
from litex.soc.cores.led import LedChaser

# CRG ----------------------------------------------------------------------------------------------

class _CRG(LiteXModule):
    def __init__(self, platform, sys_clk_freq):
        self.rst    = Signal()
        self.cd_sys = ClockDomain()

        # # #

        # Clk / Rst.
        clk27 = platform.request("clk27")  #Freq change
        rst_n = platform.request("user_btn", 0)

        # PLL.
        self.pll = pll = GW1NPLL(devicename=platform.devicename, device=platform.device)
        self.comb += pll.reset.eq(~rst_n)
        pll.register_clkin(clk27, 27e6)    #Freq change
        pll.create_clkout(self.cd_sys, sys_clk_freq)

# BaseSoC ------------------------------------------------------------------------------------------

class BaseSoC(SoCMini):
    def __init__(self, sys_clk_freq=48e6, with_led_chaser=True, **kwargs):
        platform = sipeed_tang_nano.Platform()

        # CRG --------------------------------------------------------------------------------------
        self.crg = _CRG(platform, sys_clk_freq)

        # SoCMini ----------------------------------------------------------------------------------
        kwargs["uart_name"] = "crossover"
        SoCMini.__init__(self, platform, sys_clk_freq, ident="LiteX SoC on Tang Nano", **kwargs)

        # UARTBone ---------------------------------------------------------------------------------  #disabled for now - need to select pins in previous
     #   self.add_uartbone(name="serial", baudrate=115200) 

        # Leds -------------------------------------------------------------------------------------
        if with_led_chaser:
            self.leds = LedChaser(
                pads         = platform.request_all("user_led"),
                sys_clk_freq = sys_clk_freq)

# Build --------------------------------------------------------------------------------------------

def main():
    from litex.build.parser import LiteXArgumentParser
    parser = LiteXArgumentParser(platform=sipeed_tang_nano.Platform, description="LiteX SoC on Tang Nano.")
    parser.add_target_argument("--flash",       action="store_true",      help="Flash Bitstream.")
    parser.add_target_argument("--sys-clk-freq",default=48e6, type=float, help="System clock frequency.")
    args = parser.parse_args()

    soc = BaseSoC(
        sys_clk_freq = args.sys_clk_freq,
        **parser.soc_argdict
    )

    builder = Builder(soc, **parser.builder_argdict)
    if args.build:
        builder.build(**parser.toolchain_argdict)

    if args.load:
        prog = soc.platform.create_programmer()
        prog.load_bitstream(builder.get_bitstream_filename(mode="sram"))

    if args.flash:
        prog = soc.platform.create_programmer()
        prog.flash(0, builder.get_bitstream_filename(mode="flash", ext=".fs")) # FIXME #That's not my (=

if __name__ == "__main__":
    main()
some changes to GW1NPLL class from litex.soc.cores.clock.gowin_gw1n
    @staticmethod
    def get_vco_freq_range(device):
        vco_freq_range = None
        if device.startswith('GW1NS'):
            if 'C7/I6' in device or 'C6/I5' in device:
                vco_freq_range = (600e6, 1200e6)  # datasheet says (400, 1200) but compiler enforces (600, 1200)
            elif 'C5/I4' in device:
                vco_freq_range = (320e6, 960e6) 
                 # datasheet values, not tested
        if device.startswith('GW1NZ'):  #Add this FPGA and its VCO
            if 'C6/I5' in device:
                vco_freq_range = (400e6, 800e6)  # datasheet says (400, 800)
            
        elif device.startswith('GW1N-1S'):
            vco_freq_range = (400e6, 1200e6)
        elif device.startswith('GW1N-') or device.startswith('GW1NR-'):
            vco_freq_range = (400e6, 900e6)
        if vco_freq_range is None:
            raise ValueError(f"Unsupported device {device}.")
        return vco_freq_range

    @staticmethod
    def get_pfd_freq_range(device):
        pfd_freq_range = None
        if device.startswith('GW1NS'):
            if 'C7/I6' in device or 'C6/I5' in device:
                pfd_freq_range = (3e6, 400e6)
            elif 'C5/I4' in device:
                pfd_freq_range = (3e6, 320e6)
        if device.startswith('GW1NZ'):            #Add this FPGA and its PFD
            if 'C6/I5' in device:
                pfd_freq_range = (3e6, 400e6)  # datasheet says (3, 400)
        elif device.startswith('GW1N-1S'):
            pfd_freq_range = (3e6, 400e6)  # not verified: not found in the datasheet
        elif device.startswith('GW1N-') or device.startswith('GW1NR-'):
            pfd_freq_range = (3e6, 400e6)  # not verified: not found in the datasheet
        if pfd_freq_range is None:
            raise ValueError(f"Unsupported device {device}.")
        return pfd_freq_range```

run with

python ./sipeed_tang_nano_platform.py  --build  --load --cpu-type None --csr-csv "csr.csv" --no-uart

After that I got blink on board with litex.

Can anyone check this, also are there any other changes that need to be applied to GW1NPLL class?

@trabucayre
Copy link
Contributor

My first idea was to introduce a variant arg to select between original and new. But both seems really different for pinout/LCD/etc.
It make more sense to introduce a new platform/target called sipeed_tang_nano_1k.py.
Could you explain a bit more changes required to GW1NPLL ?

@Podolyakofs
Copy link
Author

Podolyakofs commented Aug 9, 2023

From GW1NZ series of FPGA Products (look at LV - C6/I5) ( https://dl.sipeed.com/shareURL/TANG/Nano%201K/6_Chip_Manual/EN)
image

@staticmethod
    def get_vco_freq_range(device):
           vco_freq_range = None
           if device.startswith('GW1NZ'):  #Add this FPGA and its VCO (or change to startwith"GW1NZ-1")
                   if 'C6/I5' in device:
                          vco_freq_range = (400e6, 800e6)  # datasheet says (400, 800)
@staticmethod
    def get_pfd_freq_range(device):
        pfd_freq_range = None
        if device.startswith('GW1NZ'):            #Add this FPGA and its PFD (or change to startwith"GW1NZ-1")
            if 'C6/I5' in device:
                pfd_freq_range = (3e6, 400e6)  # datasheet says (3, 400)

But I'm not sure that this is enough
Device and part number is from https://github.com/sipeed/TangNano-1K-examples/blob/main/example_led/led_prj/src/led_prj.cst

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants