lambdaconcept_ecpix5.py 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. #!/usr/bin/env python3
  2. #
  3. # This file is part of LiteX-Boards.
  4. #
  5. # Copyright (c) 2020-2022 Florent Kermarrec <florent@enjoy-digital.fr>
  6. # Copyright (c) 2023 Victor Suarez Rovere <suarezvictor@gmail.com>
  7. # SPDX-License-Identifier: BSD-2-Clause
  8. from migen import *
  9. from migen.genlib.resetsync import AsyncResetSynchronizer
  10. from wpu import gen_accel_cores
  11. from litex.gen import LiteXModule
  12. from litex_boards.platforms import lambdaconcept_ecpix5
  13. from litex.soc.cores.clock import *
  14. from litex.soc.integration.soc_core import *
  15. from litex.soc.integration.builder import *
  16. from litex.soc.cores.led import LedChaser
  17. from litex.soc.cores.video import VideoDVIPHY
  18. from litex.soc.cores.bitbang import I2CMaster
  19. from litedram.modules import MT41K256M16
  20. from litedram.phy import ECP5DDRPHY
  21. from liteeth.phy.ecp5rgmii import LiteEthPHYRGMII
  22. # CRG ----------------------------------------------------------------------------------------------
  23. class _CRG(LiteXModule):
  24. def __init__(self, platform, sys_clk_freq):
  25. self.rst = Signal()
  26. self.cd_init = ClockDomain()
  27. self.cd_por = ClockDomain()
  28. self.cd_sys = ClockDomain()
  29. self.cd_sys2x = ClockDomain()
  30. self.cd_sys2x_i = ClockDomain()
  31. # # #
  32. self.stop = Signal()
  33. self.reset = Signal()
  34. # Clk / Rst
  35. clk100 = platform.request("clk100")
  36. rst_n = platform.request("rst_n")
  37. # Power on reset
  38. por_count = Signal(16, reset=2**16-1)
  39. por_done = Signal()
  40. self.comb += self.cd_por.clk.eq(clk100)
  41. self.comb += por_done.eq(por_count == 0)
  42. self.sync.por += If(~por_done, por_count.eq(por_count - 1))
  43. # PLL
  44. self.pll = pll = ECP5PLL()
  45. self.comb += pll.reset.eq(~por_done | ~rst_n | self.rst)
  46. pll.register_clkin(clk100, 100e6)
  47. pll.create_clkout(self.cd_sys2x_i, 2*sys_clk_freq)
  48. pll.create_clkout(self.cd_init, 25e6)
  49. self.specials += [
  50. Instance("ECLKSYNCB",
  51. i_ECLKI = self.cd_sys2x_i.clk,
  52. i_STOP = self.stop,
  53. o_ECLKO = self.cd_sys2x.clk),
  54. Instance("CLKDIVF",
  55. p_DIV = "2.0",
  56. i_ALIGNWD = 0,
  57. i_CLKI = self.cd_sys2x.clk,
  58. i_RST = self.reset,
  59. o_CDIVX = self.cd_sys.clk),
  60. AsyncResetSynchronizer(self.cd_sys, ~pll.locked | self.reset),
  61. ]
  62. # BaseSoC ------------------------------------------------------------------------------------------
  63. class BaseSoC(SoCCore):
  64. def __init__(self, device="85F", sys_clk_freq=int(75e6), toolchain="trellis",
  65. with_video_framebuffer = True,
  66. pixel_bus_width = 32,
  67. **kwargs):
  68. platform = lambdaconcept_ecpix5.Platform(device=device, toolchain=toolchain)
  69. if toolchain == "diamond":
  70. if platform.device.startswith("LFE5UM5G"): #diamond licenses may not support the device
  71. platform.device = "LFE5U" + platform.device[8:]
  72. # CRG --------------------------------------------------------------------------------------
  73. self.crg = _CRG(platform, sys_clk_freq)
  74. # SoCCore ----------------------------------------------------------------------------------
  75. SoCCore.__init__(self, platform, sys_clk_freq, ident="LiteX SoC on ECPIX-5", **kwargs)
  76. # DDR3 SDRAM -------------------------------------------------------------------------------
  77. if not self.integrated_main_ram_size:
  78. self.ddrphy = ECP5DDRPHY(
  79. platform.request("ddram"),
  80. sys_clk_freq=sys_clk_freq)
  81. self.comb += self.crg.stop.eq(self.ddrphy.init.stop)
  82. self.comb += self.crg.reset.eq(self.ddrphy.init.reset)
  83. self.add_sdram("sdram",
  84. phy = self.ddrphy,
  85. module = MT41K256M16(sys_clk_freq, "1:2"), #1:4 at passes memory test but video has glitches
  86. l2_cache_size = kwargs.get("l2_size", 8192)
  87. )
  88. # HDMI -------------------------------------------------------------------------------------
  89. if with_video_framebuffer:
  90. # PHY + IT6613 I2C initialization.
  91. hdmi_pads = platform.request("hdmi")
  92. self.videophy = VideoDVIPHY(hdmi_pads, clock_domain="init")
  93. self.videoi2c = I2CMaster(hdmi_pads)
  94. # I2C initialization adapted from https://github.com/ultraembedded/ecpix-5
  95. # Copyright (c) 2020 https://github.com/ultraembedded
  96. # Adapted from C to Python.
  97. REG_TX_SW_RST = 0x04
  98. B_ENTEST = (1<<7)
  99. B_REF_RST = (1<<5)
  100. B_AREF_RST = (1<<4)
  101. B_VID_RST = (1<<3)
  102. B_AUD_RST = (1<<2)
  103. B_HDMI_RST = (1<<1)
  104. B_HDCP_RST = (1<<0)
  105. REG_TX_AFE_DRV_CTRL = 0x61
  106. B_AFE_DRV_PWD = (1<<5)
  107. B_AFE_DRV_RST = (1<<4)
  108. B_AFE_DRV_PDRXDET = (1<<2)
  109. B_AFE_DRV_TERMON = (1<<1)
  110. B_AFE_DRV_ENCAL = (1<<0)
  111. REG_TX_AFE_XP_CTRL = 0x62
  112. B_AFE_XP_GAINBIT = (1<<7)
  113. B_AFE_XP_PWDPLL = (1<<6)
  114. B_AFE_XP_ENI = (1<<5)
  115. B_AFE_XP_ER0 = (1<<4)
  116. B_AFE_XP_RESETB = (1<<3)
  117. B_AFE_XP_PWDI = (1<<2)
  118. B_AFE_XP_DEI = (1<<1)
  119. B_AFE_XP_DER = (1<<0)
  120. REG_TX_AFE_ISW_CTRL = 0x63
  121. B_AFE_RTERM_SEL = (1<<7)
  122. B_AFE_IP_BYPASS = (1<<6)
  123. M_AFE_DRV_ISW = (7<<3)
  124. O_AFE_DRV_ISW = 3
  125. B_AFE_DRV_ISWK = 7
  126. REG_TX_AFE_IP_CTRL = 0x64
  127. B_AFE_IP_GAINBIT = (1<<7)
  128. B_AFE_IP_PWDPLL = (1<<6)
  129. M_AFE_IP_CKSEL = (3<<4)
  130. O_AFE_IP_CKSEL = 4
  131. B_AFE_IP_ER0 = (1<<3)
  132. B_AFE_IP_RESETB = (1<<2)
  133. B_AFE_IP_ENC = (1<<1)
  134. B_AFE_IP_EC1 = (1<<0)
  135. REG_TX_HDMI_MODE = 0xC0
  136. B_TX_HDMI_MODE = 1
  137. B_TX_DVI_MODE = 0
  138. REG_TX_GCP = 0xC1
  139. B_CLR_AVMUTE = 0
  140. B_SET_AVMUTE = 1
  141. B_TX_SETAVMUTE = (1<<0)
  142. B_BLUE_SCR_MUTE = (1<<1)
  143. B_NODEF_PHASE = (1<<2)
  144. B_PHASE_RESYNC = (1<<3)
  145. self.videoi2c.add_init(addr=0x4c, init=[
  146. # Reset.
  147. (REG_TX_SW_RST, B_REF_RST | B_VID_RST | B_AUD_RST | B_AREF_RST | B_HDCP_RST),
  148. (REG_TX_SW_RST, 0),
  149. # Select DVI Mode.
  150. (REG_TX_HDMI_MODE, B_TX_DVI_MODE),
  151. # Configure Clks.
  152. (REG_TX_SW_RST, B_AUD_RST | B_AREF_RST | B_HDCP_RST),
  153. (REG_TX_AFE_DRV_CTRL, B_AFE_DRV_RST),
  154. (REG_TX_AFE_XP_CTRL, 0x18),
  155. (REG_TX_AFE_ISW_CTRL, 0x10),
  156. (REG_TX_AFE_IP_CTRL, 0x0C),
  157. # Enable Clks.
  158. (REG_TX_AFE_DRV_CTRL, 0),
  159. # Enable Video.
  160. (REG_TX_GCP, 0),
  161. ])
  162. self.add_video_framebuffer(phy=self.videophy, timings="640x480@75Hz", clock_domain="init")
  163. # Build --------------------------------------------------------------------------------------------
  164. def add_accel_cores(soc, pixel_bus_width = 32):
  165. #corelist = ["rectangle_fill32", "ellipse_fill32"] #ellipses are currently too slow, only works with overclocking from about 47MHz to 50MHz
  166. corelist = ["rectangle_fill32", "line32"]
  167. gen_accel_cores(soc, corelist, pixel_bus_width)
  168. soc.add_constant("SDRAM_BUS_BITS", pixel_bus_width)
  169. def set_args(parser):
  170. parser.add_target_argument("--sdram-data-width", default=128, help="Set SDRAM chip data width.")
  171. parser.add_target_argument("--pixel-bus-width", default=32, help="Pixel access bus width")
  172. parser.add_target_argument("--sdram-init", default=None, help="SDRAM init file (.bin or .json).")
  173. def main():
  174. from litex.build.parser import LiteXArgumentParser
  175. parser = LiteXArgumentParser(platform=lambdaconcept_ecpix5.Platform, description="LiteX SoC on ECPIX-5")
  176. parser.add_target_argument("--device", default="85F", help="ECP5 device (45F or 85F).")
  177. parser.add_target_argument("--sys-clk-freq", default=50e6, help="System clock frequency.")
  178. set_args(parser)
  179. args = parser.parse_args()
  180. soc = BaseSoC(
  181. device = args.device,
  182. sys_clk_freq = int(float(args.sys_clk_freq)),
  183. toolchain = args.toolchain,
  184. pixel_bus_width = int(args.pixel_bus_width),
  185. **parser.soc_argdict
  186. )
  187. add_accel_cores(soc)
  188. builder = Builder(soc, **parser.builder_argdict)
  189. builder.build(**parser.toolchain_argdict, run=not args.no_compile_gateware)
  190. if __name__ == "__main__":
  191. main()