Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
#!/usr/bin/env python3
#
# This file is part of LiteX-Boards.
#
# Copyright (c) 2021 Nathaniel Lewis <github@nrlewis.dev>
# SPDX-License-Identifier: BSD-2-Clause
# Testing build for HDMI
# - The main trouble with HDMI demos are that they require many SLICEMs, which are a very limited
# resource on the XC6SLX9. Many of these examples are just trying to reduce usage of them.
#
# # Simple colorbar output
# ./alchitry_mojo.py \
# --build \
# --with-hdmi-shield \
# --with-video-colorbars \
# --csr-csv=build/alchitry_mojo/csr.csv
#
# # Video Terminal (lower SRAM size to allow for text buffer)
# ./alchitry_mojo.py \
# --build \
# --with-hdmi-shield \
# --with-video-terminal \
# --csr-csv=build/alchitry_mojo/csr.csv \
# --integrated-rom-size 32768 \
# --integrated-sram-size 4096
#
# # Video Framebuffer (double sdram speed to have enough bandwidth)
# # Lower the fifo_depth in litex/litex/soc/cores/video.py "class VideoFrameBuffer" to 1024
# ./alchitry_mojo.py \
# --build \
# --with-hdmi-shield \
# --with-video-framebuffer \
# --csr-csv=build/alchitry_mojo/csr.csv \
# --integrated-rom-size 32768 \
# --sdram-rate 1:2
#
# litex> # Turn screen Red
# litex> mem_write 0x40c00000 0xffff0000 307200
import os
import argparse
import sys
from migen import *
from litex.build.io import DDROutput
from litex_boards.platforms import alchitry_mojo
from litex.soc.interconnect.csr import *
from litex.soc.integration.soc_core import *
from litex.soc.integration.builder import *
from litex.soc.cores.clock import *
from litex.soc.cores.video import VideoS6HDMIPHY
from litex.soc.cores.led import LedChaser
from litedram.modules import MT48LC32M8, SDRModule
from litedram.phy import GENSDRPHY, HalfRateGENSDRPHY
# CRG ----------------------------------------------------------------------------------------------
class CRG(Module):
def __init__(self, platform, sys_clk_freq, sdram_rate="1:1"):
self.rst = Signal()
self.clock_domains.cd_sys = ClockDomain()
self.clock_domains.cd_hdmi = ClockDomain()
self.clock_domains.cd_hdmi5x = ClockDomain()
if sdram_rate == "1:2":
self.clock_domains.cd_sys2x = ClockDomain(reset_less=True)
self.clock_domains.cd_sys2x_ps = ClockDomain(reset_less=True)
else:
self.clock_domains.cd_sys_ps = ClockDomain(reset_less=True)
# Clk/Rst
clk50 = platform.request("clk50")
rst = platform.request("cpu_reset")
avr_ready = platform.request("cclk")
# PLL
self.submodules.pll = pll = S6PLL()
self.comb += pll.reset.eq(~rst | ~avr_ready | self.rst)
pll.register_clkin(clk50, 50e6)
pll.create_clkout(self.cd_sys, sys_clk_freq)
pll.create_clkout(self.cd_hdmi, 25e6, margin=0)
pll.create_clkout(self.cd_hdmi5x, 125e6, margin=0)
if sdram_rate == "1:2":
pll.create_clkout(self.cd_sys2x, 2*sys_clk_freq)
pll.create_clkout(self.cd_sys2x_ps, 2*sys_clk_freq, phase=90)
else:
pll.create_clkout(self.cd_sys_ps, sys_clk_freq, phase=90)
# BaseSoC -----------------------------------------------------------------------------------------
class BaseSoC(SoCCore):
def __init__(self, sys_clk_freq=int(62.5e6), sdram_rate="1:1", with_hdmi_shield=False,
with_sdram_shield=False, with_led_chaser=True, with_video_terminal=False,
with_video_framebuffer=False, with_video_colorbars=False, **kwargs):
platform = alchitry_mojo.Platform()
# SoCCore ----------------------------------------------------------------------------------
SoCCore.__init__(self, platform, sys_clk_freq,
ident = "LiteX SoC on Alchitry Mojo",
ident_version = True,
**kwargs)
# CRG --------------------------------------------------------------------------------------
self.submodules.crg = CRG(platform, sys_clk_freq, sdram_rate)
# HDMI Shield ------------------------------------------------------------------------------
if with_hdmi_shield:
self.platform.add_extension(alchitry_mojo._hdmi_shield)
# SDRAM Shield -----------------------------------------------------------------------------
if with_sdram_shield:
self.platform.add_extension(alchitry_mojo._sdram_shield)
# Add SDRAM if a shield with RAM has been added
if not self.integrated_main_ram_size and (with_hdmi_shield or with_sdram_shield):
sdram_clk = ClockSignal("sys2x_ps" if sdram_rate == "1:2" else "sys_ps")
self.crg.specials += DDROutput(1, 0, platform.request("sdram_clock"), sdram_clk)
sdrphy_cls = HalfRateGENSDRPHY if sdram_rate == "1:2" else GENSDRPHY
self.submodules.sdrphy = sdrphy_cls(platform.request("sdram"), sys_clk_freq)
self.add_sdram("sdram",
phy = self.sdrphy,
module = MT48LC32M8(sys_clk_freq, sdram_rate),
l2_cache_size = kwargs.get("l2_size", 1024)
)
# HDMI Options -----------------------------------------------------------------------------
if with_hdmi_shield and (with_video_colorbars or with_video_framebuffer or with_video_terminal):
self.submodules.videophy = VideoS6HDMIPHY(platform.request("hdmi_out"), clock_domain="hdmi")
if with_video_colorbars:
self.add_video_colorbars(phy=self.videophy, timings="640x480@60Hz", clock_domain="hdmi")
if with_video_terminal:
self.add_video_terminal(phy=self.videophy, timings="640x480@60Hz", clock_domain="hdmi")
if with_video_framebuffer:
self.add_video_framebuffer(phy=self.videophy, timings="640x480@60Hz", clock_domain="hdmi")
# Leds -------------------------------------------------------------------------------------
if with_led_chaser:
self.submodules.leds = LedChaser(
pads = platform.request_all("user_led"),
sys_clk_freq = sys_clk_freq)
# Build --------------------------------------------------------------------------------------------
def main():
parser = argparse.ArgumentParser(description="LiteX SoC on Alchitry Mojo")
parser.add_argument("--build", action="store_true", help="Build bitstream")
parser.add_argument("--sys-clk-freq", default=62.5e6, help="System clock frequency (default: 62.5 MHz)")
parser.add_argument("--sdram-rate", default="1:1", help="SDRAM Rate: 1:1 Full Rate (default), 1:2 Half Rate")
shields1 = parser.add_mutually_exclusive_group()
shields1.add_argument("--with-hdmi-shield", action="store_true", help="Enable HDMI Shield")
shields1.add_argument("--with-sdram-shield", action="store_true", help="Enable SDRAM Shield")
viopts = parser.add_mutually_exclusive_group()
viopts.add_argument("--with-video-terminal", action="store_true", help="Enable Video Terminal (HDMI)")
viopts.add_argument("--with-video-framebuffer", action="store_true", help="Enable Video Framebuffer (HDMI)")
viopts.add_argument("--with-video-colorbars", action="store_true", help="Enable Video Colorbars (HDMI)")
builder_args(parser)
soc_core_args(parser)
args = parser.parse_args()
# Note: baudrate is fixed because regardless of USB->TTL baud, the AVR <-> FPGA baudrate is
# set to a fixed rate of 500 kilobaud.
soc = BaseSoC(
sys_clk_freq = int(float(args.sys_clk_freq)),
sdram_rate = args.sdram_rate,
with_hdmi_shield = args.with_hdmi_shield,
with_sdram_shield = args.with_sdram_shield,
with_video_terminal = args.with_video_terminal,
with_video_framebuffer = args.with_video_framebuffer,
with_video_colorbars = args.with_video_colorbars,
uart_baudrate = 500000,
**soc_core_argdict(args)
)
builder = Builder(soc, **builder_argdict(args))
builder.build(run=args.build)
if __name__ == "__main__":
main()