5 from functools
import reduce
6 from operator
import or_
8 from migen
import (Signal
, FSM
, If
, Display
, Finish
, NextValue
, NextState
,
9 Cat
, Record
, ClockSignal
, wrap
, ResetInserter
,
10 ClockDomain
, ResetSignal
)
12 from litex
.build
.generic_platform
import Pins
, Subsignal
13 from litex
.build
.sim
import SimPlatform
14 from litex
.build
.io
import CRG
15 from litex
.build
.sim
.config
import SimConfig
17 from litex
.soc
.integration
.soc
import SoCRegion
18 from litex
.soc
.integration
.soc_core
import SoCCore
19 from litex
.soc
.integration
.soc_sdram
import SoCSDRAM
20 from litex
.soc
.integration
.builder
import Builder
21 from litex
.soc
.integration
.common
import get_mem_data
23 from litedram
import modules
as litedram_modules
24 from litedram
.phy
.model
import SDRAMPHYModel
25 #from litedram.phy.gensdrphy import GENSDRPHY, HalfRateGENSDRPHY
26 from litedram
.common
import PHYPadsCombiner
, PhySettings
27 from litedram
.phy
.dfi
import Interface
as DFIInterface
28 from litex
.soc
.cores
.spi
import SPIMaster
29 from litex
.soc
.cores
.bitbang
import SPIMaster
as SPIMasterBitbang
30 from litex
.soc
.cores
.pwm
import PWM
31 #from litex.soc.cores.bitbang import I2CMaster
32 from litex
.soc
.cores
import uart
34 from litex
.tools
.litex_sim
import sdram_module_nphases
, get_sdram_phy_settings
36 from litex
.tools
.litex_sim
import Platform
37 from libresoc
.ls180
import LS180Platform
39 from migen
import Module
40 from litex
.soc
.interconnect
.csr
import AutoCSR
42 from libresoc
import LibreSoC
43 from microwatt
import Microwatt
46 from litex
.soc
.integration
.soc
import SoCCSRHandler
47 SoCCSRHandler
.supported_address_width
.append(12)
48 SoCCSRHandler
.supported_address_width
.append(13)
50 # GPIO Tristate -------------------------------------------------------
51 # doesn't work properly.
52 #from litex.soc.cores.gpio import GPIOTristate
53 from litex
.soc
.interconnect
.csr
import CSRStorage
, CSRStatus
, CSRField
54 from migen
.genlib
.cdc
import MultiReg
57 from litex
.soc
.interconnect
import wishbone
58 from litesdcard
.phy
import (SDPHY
, SDPHYClocker
,
59 SDPHYInit
, SDPHYCMDW
, SDPHYCMDR
,
60 SDPHYDATAW
, SDPHYDATAR
,
62 from litesdcard
.core
import SDCore
63 from litesdcard
.frontend
.dma
import SDBlock2MemDMA
, SDMem2BlockDMA
64 from litex
.build
.io
import SDROutput
, SDRInput
67 # I2C Master Bit-Banging --------------------------------------------------
69 class I2CMaster(Module
, AutoCSR
):
70 """I2C Master Bit-Banging
72 Provides the minimal hardware to do software I2C Master bit banging.
74 On the same write CSRStorage (_w), software can control SCL (I2C_SCL),
75 SDA direction and value (I2C_OE, I2C_W). Software get back SDA value
76 with the read CSRStatus (_r).
78 pads_layout
= [("scl", 1), ("sda", 1)]
79 def __init__(self
, pads
):
81 self
._w
= CSRStorage(fields
=[
82 CSRField("scl", size
=1, offset
=0),
83 CSRField("oe", size
=1, offset
=1),
84 CSRField("sda", size
=1, offset
=2)],
86 self
._r
= CSRStatus(fields
=[
87 CSRField("sda", size
=1, offset
=0)],
92 def connect(self
, pads
):
97 pads
.scl
.eq(self
._w
.fields
.scl
),
98 pads
.sda_oe
.eq( self
._w
.fields
.oe
),
99 pads
.sda_o
.eq( self
._w
.fields
.sda
),
100 self
._r
.fields
.sda
.eq(pads
.sda_i
),
104 class GPIOTristateASIC(Module
, AutoCSR
):
105 def __init__(self
, name
, pads
, prange
=None):
107 prange
= range(nbits
)
110 self
._oe
= CSRStorage(nbits
, description
="GPIO Tristate(s) Control.")
111 self
._in
= CSRStatus(nbits
, description
="GPIO Input(s) Status.")
112 self
._out
= CSRStorage(nbits
, description
="GPIO Ouptut(s) Control.")
116 _pads
= Record( ((name
+"i", nbits
),
119 _o
= getattr(_pads
, name
+"o")
120 _oe
= getattr(_pads
, name
+"oe")
121 _i
= getattr(_pads
, name
+"i")
122 for j
, i
in enumerate(prange
):
123 self
.comb
+= _i
[j
].eq(pads
.i
[i
])
124 self
.comb
+= pads
.o
[i
].eq(_o
[j
])
125 self
.comb
+= pads
.oe
[i
].eq(_oe
[j
])
128 o
= self
._out
.storage
129 oe
= self
._oe
.storage
131 for j
in range(nbits
):
132 self
.specials
+= SDROutput(clk
=clk
, i
=oe
[j
], o
=_oe
[j
])
133 self
.specials
+= SDROutput(clk
=clk
, i
=o
[j
], o
=_o
[j
])
134 self
.specials
+= SDRInput(clk
=clk
, i
=_i
[j
], o
=i
[j
])
135 #for i in range(nbits):
136 #self.comb += _pads.oe[i].eq(self._oe.storage[i])
137 #self.comb += _pads.o[i].eq(self._out.storage[i])
138 #self.specials += MultiReg(_pads.i[i], self._in.status[i])
140 # SDCard PHY IO -------------------------------------------------------
142 class SDRPad(Module
):
143 def __init__(self
, pad
, name
, o
, oe
, i
):
145 _o
= getattr(pad
, "%s_o" % name
)
146 _oe
= getattr(pad
, "%s_oe" % name
)
147 _i
= getattr(pad
, "%s_i" % name
)
148 for j
in range(len(_o
)):
149 self
.specials
+= SDROutput(clk
=clk
, i
=oe
, o
=_oe
[j
])
150 self
.specials
+= SDROutput(clk
=clk
, i
=o
[j
], o
=_o
[j
])
151 self
.specials
+= SDRInput(clk
=clk
, i
=_i
[j
], o
=i
[j
])
154 class SDPHYIOGen(Module
):
155 def __init__(self
, clocker
, sdpads
, pads
):
157 if hasattr(pads
, "rst"):
158 self
.comb
+= pads
.rst
.eq(0)
161 self
.specials
+= SDROutput(
163 i
= ~clocker
.clk
& sdpads
.clk
,
169 self
.submodules
.sd_cmd
= SDRPad(pads
, "cmd", c
.o
, c
.oe
, c
.i
)
173 self
.submodules
.sd_data
= SDRPad(pads
, "data", d
.o
, d
.oe
, d
.i
)
176 class SDPHY(Module
, AutoCSR
):
177 def __init__(self
, pads
, device
, sys_clk_freq
,
178 cmd_timeout
=10e-3, data_timeout
=10e-3):
179 self
.card_detect
= CSRStatus() # Assume SDCard is present if no cd pin.
180 self
.comb
+= self
.card_detect
.status
.eq(getattr(pads
, "cd", 0))
182 self
.submodules
.clocker
= clocker
= SDPHYClocker()
183 self
.submodules
.init
= init
= SDPHYInit()
184 self
.submodules
.cmdw
= cmdw
= SDPHYCMDW()
185 self
.submodules
.cmdr
= cmdr
= SDPHYCMDR(sys_clk_freq
,
187 self
.submodules
.dataw
= dataw
= SDPHYDATAW()
188 self
.submodules
.datar
= datar
= SDPHYDATAR(sys_clk_freq
,
193 self
.sdpads
= sdpads
= Record(_sdpads_layout
)
196 sdphy_cls
= SDPHYIOGen
197 self
.submodules
.io
= sdphy_cls(clocker
, sdpads
, pads
)
199 # Connect pads_out of submodules to physical pads --------------
200 pl
= [init
, cmdw
, cmdr
, dataw
, datar
]
202 sdpads
.clk
.eq( reduce(or_
, [m
.pads_out
.clk
for m
in pl
])),
203 sdpads
.cmd
.oe
.eq( reduce(or_
, [m
.pads_out
.cmd
.oe
for m
in pl
])),
204 sdpads
.cmd
.o
.eq( reduce(or_
, [m
.pads_out
.cmd
.o
for m
in pl
])),
205 sdpads
.data
.oe
.eq(reduce(or_
, [m
.pads_out
.data
.oe
for m
in pl
])),
206 sdpads
.data
.o
.eq( reduce(or_
, [m
.pads_out
.data
.o
for m
in pl
])),
209 self
.comb
+= m
.pads_out
.ready
.eq(self
.clocker
.ce
)
211 # Connect physical pads to pads_in of submodules ---------------
213 self
.comb
+= m
.pads_in
.valid
.eq(self
.clocker
.ce
)
214 self
.comb
+= m
.pads_in
.cmd
.i
.eq(sdpads
.cmd
.i
)
215 self
.comb
+= m
.pads_in
.data
.i
.eq(sdpads
.data
.i
)
217 # Speed Throttling -------------------------------------------
218 self
.comb
+= clocker
.stop
.eq(dataw
.stop | datar
.stop
)
221 # Generic SDR PHY ---------------------------------------------------------
223 class GENSDRPHY(Module
):
224 def __init__(self
, pads
, cl
=2, cmd_latency
=1):
225 pads
= PHYPadsCombiner(pads
)
226 addressbits
= len(pads
.a
)
227 bankbits
= len(pads
.ba
)
228 nranks
= 1 if not hasattr(pads
, "cs_n") else len(pads
.cs_n
)
229 databits
= len(pads
.dq_i
)
231 assert databits
%8 == 0
233 # PHY settings ----------------------------------------------------
234 self
.settings
= PhySettings(
235 phytype
= "GENSDRPHY",
238 dfi_databits
= databits
,
246 read_latency
= cl
+ cmd_latency
,
250 # DFI Interface ---------------------------------------------------
251 self
.dfi
= dfi
= DFIInterface(addressbits
, bankbits
, nranks
, databits
)
255 # Iterate on pads groups ------------------------------------------
256 for pads_group
in range(len(pads
.groups
)):
257 pads
.sel_group(pads_group
)
259 # Addresses and Commands --------------------------------------
261 self
.specials
+= [SDROutput(i
=p0
.address
[i
], o
=pads
.a
[i
])
262 for i
in range(len(pads
.a
))]
263 self
.specials
+= [SDROutput(i
=p0
.bank
[i
], o
=pads
.ba
[i
])
264 for i
in range(len(pads
.ba
))]
265 self
.specials
+= SDROutput(i
=p0
.cas_n
, o
=pads
.cas_n
)
266 self
.specials
+= SDROutput(i
=p0
.ras_n
, o
=pads
.ras_n
)
267 self
.specials
+= SDROutput(i
=p0
.we_n
, o
=pads
.we_n
)
268 if hasattr(pads
, "cke"):
269 for i
in range(len(pads
.cke
)):
270 self
.specials
+= SDROutput(i
=p0
.cke
[i
], o
=pads
.cke
[i
])
271 if hasattr(pads
, "cs_n"):
272 for i
in range(len(pads
.cs_n
)):
273 self
.specials
+= SDROutput(i
=p0
.cs_n
[i
], o
=pads
.cs_n
[i
])
275 # DQ/DM Data Path -------------------------------------------------
279 self
.submodules
.dq
= SDRPad(pads
, "dq", d
.wrdata
, d
.wrdata_en
, d
.rddata
)
281 if hasattr(pads
, "dm"):
282 print ("sdr pads dm len", pads
.dm
, len(pads
.dm
))
283 for i
in range(len(pads
.dm
)):
284 self
.specials
+= SDROutput(i
=d
.wrdata_en
&d
.wrdata_mask
[i
],
287 # DQ/DM Control Path ----------------------------------------------
288 rddata_en
= Signal(cl
+ cmd_latency
)
289 self
.sync
+= rddata_en
.eq(Cat(dfi
.p0
.rddata_en
, rddata_en
))
290 self
.sync
+= dfi
.p0
.rddata_valid
.eq(rddata_en
[-1])
293 # LibreSoC 180nm ASIC -------------------------------------------------------
295 class LibreSoCSim(SoCCore
):
296 def __init__(self
, cpu
="libresoc", debug
=False, with_sdram
=True,
297 sdram_module
= "AS4C16M16",
298 #sdram_data_width = 16,
299 #sdram_module = "MT48LC16M16",
300 sdram_data_width
= 16,
301 irq_reserved_irqs
= {'uart': 0},
306 assert cpu
in ["libresoc", "microwatt"]
307 sys_clk_freq
= int(50e6
)
309 platform_name
= platform
310 if platform
== 'sim':
311 platform
= Platform()
312 self
.platform
.name
= 'ls180'
314 elif 'ls180' in platform
:
315 platform
= LS180Platform()
322 variant
= "ls180sram4k"
324 variant
= "ls180nopll"
326 print ("CPU, variant", platform_name
, variant
)
328 # reserve XICS ICP and XICS memory addresses.
329 self
.mem_map
['xics_icp'] = 0xc0010000
330 self
.mem_map
['xics_ics'] = 0xc0011000
331 #self.csr_map["icp"] = 8 # 8 x 0x800 == 0x4000
332 #self.csr_map["ics"] = 10 # 10 x 0x800 == 0x5000
336 #ram_init = get_mem_data({
337 # ram_fname: "0x00000000",
339 ram_init
= get_mem_data(ram_fname
, "little")
341 # remap the main RAM to reset-start-address
343 # without sram nothing works, therefore move it to higher up
344 self
.mem_map
["sram"] = 0x90000000
346 # put UART at 0xc000200 (w00t! this works!)
347 self
.csr_map
["uart"] = 4
349 self
.mem_map
["main_ram"] = 0x90000000
351 self
.mem_map
["sram"] = 0x00000000
352 self
.mem_map
["sram1"] = 0x00000200
353 self
.mem_map
["sram2"] = 0x00000400
354 self
.mem_map
["sram3"] = 0x00000600
355 self
.mem_map
["sram4"] = 0x00000800
358 sram_size
= 0x80 # ridiculously small
359 if "sram4k" not in variant
:
360 sram_size
= 0x200 # no 4k SRAMs, make slightly bigger
361 self
.mem_map
["sram"] = 0x00000000
362 self
.mem_map
["sram1"] = 0x00000700
363 self
.mem_map
["sram4k_0"] = 0x00001000
364 self
.mem_map
["sram4k_1"] = 0x00002000
365 self
.mem_map
["sram4k_2"] = 0x00003000
366 self
.mem_map
["sram4k_3"] = 0x00004000
368 # SoCCore -------------------------------------------------------------
369 SoCCore
.__init
__(self
, platform
, clk_freq
=sys_clk_freq
,
370 cpu_type
= "microwatt",
371 cpu_cls
= LibreSoC
if cpu
== "libresoc" \
373 #bus_data_width = 64, # don't add this! stops conversion
374 csr_address_width
= 13, # limit to 0x8000
375 cpu_variant
= variant
,
380 with_sdram
= with_sdram
,
381 sdram_module
= sdram_module
,
382 sdram_data_width
= sdram_data_width
,
383 integrated_rom_size
= 0, # if ram_fname else 0x10000,
384 #integrated_sram_size = 0x1000, - problem with yosys ABC
385 integrated_sram_size
= sram_size
,
386 #integrated_main_ram_init = ram_init,
387 integrated_main_ram_size
= 0x00000000 if with_sdram \
388 else 0x10000000 , # 256MB
391 self
.platform
.name
= platform_name
394 # add 4 more 4k integrated SRAMs
395 self
.add_ram("sram1", self
.mem_map
["sram1"], 0x200)
396 self
.add_ram("sram2", self
.mem_map
["sram2"], 0x200)
397 self
.add_ram("sram3", self
.mem_map
["sram3"], 0x200)
398 self
.add_ram("sram4", self
.mem_map
["sram4"], 0x200)
400 self
.add_ram("sram1", self
.mem_map
["sram1"], 0x80) # tiny!
402 # SDR SDRAM ----------------------------------------------
403 if False: # not self.integrated_main_ram_size:
404 self
.submodules
.sdrphy
= sdrphy_cls(platform
.request("sdram"))
406 if cpu
== "libresoc":
407 # XICS interrupt devices
408 icp_addr
= self
.mem_map
['xics_icp']
409 icp_wb
= self
.cpu
.xics_icp
410 icp_region
= SoCRegion(origin
=icp_addr
, size
=0x20, cached
=False)
411 self
.bus
.add_slave(name
='icp', slave
=icp_wb
, region
=icp_region
)
413 ics_addr
= self
.mem_map
['xics_ics']
414 ics_wb
= self
.cpu
.xics_ics
415 ics_region
= SoCRegion(origin
=ics_addr
, size
=0x1000, cached
=False)
416 self
.bus
.add_slave(name
='ics', slave
=ics_wb
, region
=ics_region
)
419 for i
, sram_wb
in enumerate(self
.cpu
.srams
):
420 name
= 'sram4k_%d' % i
421 sram_adr
= self
.mem_map
[name
]
422 ics_region
= SoCRegion(origin
=sram_adr
, size
=0x1000)
423 self
.bus
.add_slave(name
=name
, slave
=sram_wb
, region
=ics_region
)
425 # CRG -----------------------------------------------------------------
426 # power-on-reset still based on PLL, leave sys_rst HI until
428 pll_clk
= self
.cpu
.pllclk_o
# PLL into cpu
429 self
.submodules
.crg
= CRG(pll_clk
,
430 platform
.request("sys_rst"))
432 if hasattr(self
.cpu
, "clk_sel"):
434 clksel_i
= platform
.request("sys_clksel_i")
435 pll_test_o
= platform
.request("sys_pll_testout_o")
436 pll_vco_o
= platform
.request("sys_pll_vco_o")
438 self
.comb
+= self
.cpu
.clk_sel
.eq(clksel_i
) # allow clock src select
439 self
.comb
+= pll_test_o
.eq(self
.cpu
.pll_test_o
) # "test" from PLL
440 self
.comb
+= pll_vco_o
.eq(self
.cpu
.pll_vco_o
) # PLL lock flag
441 cd_cpu
= ClockDomain()
442 cd_pll
= ClockDomain("pll", reset_less
=True)
443 self
.clock_domains
.cd_pll
= cd_pll
444 sys_clk
= platform
.request("sys_pllclk") # incoming clock
445 self
.comb
+= self
.cpu
.pll_24_i
.eq(sys_clk
)
446 self
.comb
+= self
.cd_pll
.clk
.eq(self
.cpu
.pllclk_o
) # PLL into cpu
447 #self.comb += self.cd_cpu.rst.eq(ResetSignal())
448 #self.comb += self.cpu.cpu_clk.eq(cd_cpu.clk)
452 # SDRAM ----------------------------------------------------
454 sdram_clk_freq
= int(100e6
) # FIXME: use 100MHz timings
455 sdram_module_cls
= getattr(litedram_modules
, sdram_module
)
456 sdram_rate
= "1:{}".format(
457 sdram_module_nphases
[sdram_module_cls
.memtype
])
458 sdram_module
= sdram_module_cls(sdram_clk_freq
, sdram_rate
)
459 phy_settings
= get_sdram_phy_settings(
460 memtype
= sdram_module
.memtype
,
461 data_width
= sdram_data_width
,
462 clk_freq
= sdram_clk_freq
)
463 #sdrphy_cls = HalfRateGENSDRPHY
464 sdrphy_cls
= GENSDRPHY
465 sdram_pads
= self
.cpu
.cpupads
['sdr']
466 self
.submodules
.sdrphy
= sdrphy_cls(sdram_pads
)
467 #self.submodules.sdrphy = sdrphy_cls(sdram_module,
471 self
.add_sdram("sdram",
473 module
= sdram_module
,
474 origin
= self
.mem_map
["main_ram"],
476 l2_cache_size
= 0, # 8192
477 l2_cache_min_data_width
= 128,
478 l2_cache_reverse
= True
480 # FIXME: skip memtest to avoid corrupting memory
481 self
.add_constant("MEMTEST_BUS_SIZE", 128//16)
482 self
.add_constant("MEMTEST_DATA_SIZE", 128//16)
483 self
.add_constant("MEMTEST_ADDR_SIZE", 128//16)
484 self
.add_constant("MEMTEST_BUS_DEBUG", 1)
485 self
.add_constant("MEMTEST_ADDR_DEBUG", 1)
486 self
.add_constant("MEMTEST_DATA_DEBUG", 1)
489 sys_clk
= ClockSignal()
490 #sdr_clk = self.cpu.cpupads['sdram_clock']
491 sdr_clk
= sdram_pads
.clock
492 #self.specials += DDROutput(1, 0, , sdram_clk)
493 self
.specials
+= SDROutput(clk
=sys_clk
, i
=sys_clk
, o
=sdr_clk
)
496 uart_core_pads
= self
.cpu
.cpupads
['uart']
497 self
.submodules
.uart_phy
= uart
.UARTPHY(
498 pads
= uart_core_pads
,
499 clk_freq
= self
.sys_clk_freq
,
501 self
.submodules
.uart
= ResetInserter()(uart
.UART(self
.uart_phy
,
505 self
.csr
.add("uart_phy", use_loc_if_exists
=True)
506 self
.csr
.add("uart", use_loc_if_exists
=True)
507 self
.irq
.add("uart", use_loc_if_exists
=True)
509 # GPIOs (bi-directional)
510 gpio_core_pads
= self
.cpu
.cpupads
['gpio']
511 self
.submodules
.gpio0
= GPIOTristateASIC("gpio0", gpio_core_pads
,
513 self
.add_csr("gpio0")
515 self
.submodules
.gpio1
= GPIOTristateASIC("gpio1", gpio_core_pads
,
517 self
.add_csr("gpio1")
520 print ("cpupadkeys", self
.cpu
.cpupads
.keys())
521 if 'mspi0' in self
.cpu
.cpupads
:
522 pads
= self
.cpu
.cpupads
['mspi0']
523 if False: # XXX needs to be greater than 1-bit wide, use bitbang
525 spimaster
= SPIMaster(pads
, 4, self
.sys_clk_freq
, sd_clk_freq
)
526 spimaster
.add_clk_divider()
528 spimaster
= SPIMasterBitbang(pads
)
529 setattr(self
.submodules
, 'spimaster', spimaster
)
530 self
.add_csr('spimaster')
532 if 'mspi1' in self
.cpu
.cpupads
:
533 # SPI SDCard (1 wide)
535 pads
= self
.cpu
.cpupads
['mspi1']
536 spisdcard
= SPIMaster(pads
, 2, self
.sys_clk_freq
, spi_clk_freq
)
537 spisdcard
.add_clk_divider()
538 setattr(self
.submodules
, 'spisdcard', spisdcard
)
539 self
.add_csr('spisdcard')
541 # EINTs - very simple, wire up top 3 bits to ls180 "eint" pins
542 eintpads
= self
.cpu
.cpupads
['eint']
543 print ("eintpads", eintpads
)
544 self
.eint_tmp
= Signal(len(eintpads
))
545 for i
in range(len(eintpads
)):
546 self
.comb
+= self
.cpu
.interrupt
[13+i
].eq(self
.eint_tmp
[i
])
547 self
.comb
+= self
.eint_tmp
[i
].eq(getattr(eintpads
, "%d" % i
))
550 jtagpads
= platform
.request("jtag")
551 self
.comb
+= self
.cpu
.jtag_tck
.eq(jtagpads
.tck
)
552 self
.comb
+= self
.cpu
.jtag_tms
.eq(jtagpads
.tms
)
553 self
.comb
+= self
.cpu
.jtag_tdi
.eq(jtagpads
.tdi
)
554 self
.comb
+= jtagpads
.tdo
.eq(self
.cpu
.jtag_tdo
)
556 # NC - allows some iopads to be connected up
557 # sigh, just do something, anything, to stop yosys optimising these out
558 nc_pads
= platform
.request("nc")
559 num_nc
= len(nc_pads
)
560 self
.nc
= Signal(num_nc
)
561 self
.comb
+= self
.nc
.eq(nc_pads
)
562 self
.dummy
= Signal(num_nc
)
563 for i
in range(num_nc
):
564 self
.sync
+= self
.dummy
[i
].eq(self
.nc
[i
] | self
.cpu
.interrupt
[0])
567 if hasattr(self
.cpu
.cpupads
, 'pwm'):
568 pwmpads
= self
.cpu
.cpupads
['pwm']
571 setattr(self
.submodules
, name
, PWM(pwmpads
[i
]))
575 i2c_core_pads
= self
.cpu
.cpupads
['mtwi']
576 self
.submodules
.i2c
= I2CMaster(i2c_core_pads
)
579 # SDCard -----------------------------------------------------
581 if hasattr(self
.cpu
.cpupads
, 'sd0'):
583 sdcard_pads
= self
.cpu
.cpupads
['sd0']
586 self
.submodules
.sdphy
= SDPHY(sdcard_pads
,
587 self
.platform
.device
, self
.clk_freq
)
588 self
.submodules
.sdcore
= SDCore(self
.sdphy
)
589 self
.add_csr("sdphy")
590 self
.add_csr("sdcore")
593 bus
= wishbone
.Interface(data_width
=self
.bus
.data_width
,
594 adr_width
=self
.bus
.address_width
)
595 self
.submodules
.sdblock2mem
= SDBlock2MemDMA(bus
=bus
,
596 endianness
=self
.cpu
.endianness
)
597 self
.comb
+= self
.sdcore
.source
.connect(self
.sdblock2mem
.sink
)
598 dma_bus
= self
.bus
if not hasattr(self
, "dma_bus") else self
.dma_bus
599 dma_bus
.add_master("sdblock2mem", master
=bus
)
600 self
.add_csr("sdblock2mem")
603 bus
= wishbone
.Interface(data_width
=self
.bus
.data_width
,
604 adr_width
=self
.bus
.address_width
)
605 self
.submodules
.sdmem2block
= SDMem2BlockDMA(bus
=bus
,
606 endianness
=self
.cpu
.endianness
)
607 self
.comb
+= self
.sdmem2block
.source
.connect(self
.sdcore
.sink
)
608 dma_bus
= self
.bus
if not hasattr(self
, "dma_bus") else self
.dma_bus
609 dma_bus
.add_master("sdmem2block", master
=bus
)
610 self
.add_csr("sdmem2block")
612 # Debug ---------------------------------------------------------------
616 jtag_en
= ('jtag' in variant
) or ('ls180' in variant
)
618 # setup running of DMI FSM
621 dmi_dout
= Signal(64)
627 dbg_dout
= Signal(64)
630 # capture pc from dmi
632 active_dbg
= Signal()
633 active_dbg_cr
= Signal()
634 active_dbg_xer
= Signal()
643 # increment counter, Stop after 100000 cycles
645 self
.sync
+= uptime
.eq(uptime
+ 1)
646 #self.sync += If(uptime == 1000000000000, Finish())
648 # DMI FSM counter and FSM itself
649 dmicount
= Signal(10)
650 dmirunning
= Signal(1)
651 dmi_monitor
= Signal(1)
653 self
.submodules
+= dmifsm
657 If(dmi_req
& dmi_wen
,
658 (self
.cpu
.dmi_addr
.eq(dmi_addr
), # DMI Addr
659 self
.cpu
.dmi_din
.eq(dmi_din
), # DMI in
660 self
.cpu
.dmi_req
.eq(1), # DMI request
661 self
.cpu
.dmi_wr
.eq(1), # DMI write
668 If(dmi_req
& ~dmi_wen
,
669 (self
.cpu
.dmi_addr
.eq(dmi_addr
), # DMI Addr
670 self
.cpu
.dmi_req
.eq(1), # DMI request
671 self
.cpu
.dmi_wr
.eq(0), # DMI read
673 # acknowledge received: capture data.
675 NextValue(dbg_addr
, dmi_addr
),
676 NextValue(dbg_dout
, self
.cpu
.dmi_dout
),
677 NextValue(dbg_msg
, 1),
684 # DMI response received: reset the dmi request and check if
688 NextState("FIRE_MONITOR"), # fire "monitor" on next cycle
690 NextState("START"), # back to start on next cycle
692 NextValue(dmi_req
, 0),
693 NextValue(dmi_addr
, 0),
694 NextValue(dmi_din
, 0),
695 NextValue(dmi_wen
, 0),
698 # "monitor" mode fires off a STAT request
699 dmifsm
.act("FIRE_MONITOR",
700 (NextValue(dmi_req
, 1),
701 NextValue(dmi_addr
, 1), # DMI STAT address
702 NextValue(dmi_din
, 0),
703 NextValue(dmi_wen
, 0), # read STAT
704 NextState("START"), # back to start on next cycle
708 self
.comb
+= xer_so
.eq((dbg_dout
& 1) == 1)
709 self
.comb
+= xer_ca
.eq((dbg_dout
& 4) == 4)
710 self
.comb
+= xer_ca32
.eq((dbg_dout
& 8) == 8)
711 self
.comb
+= xer_ov
.eq((dbg_dout
& 16) == 16)
712 self
.comb
+= xer_ov32
.eq((dbg_dout
& 32) == 32)
715 self
.sync
+= If(dbg_msg
,
716 (If(active_dbg
& (dbg_addr
== 0b10), # PC
717 Display("pc : %016x", dbg_dout
),
719 If(dbg_addr
== 0b10, # PC
720 pc
.eq(dbg_dout
), # capture PC
722 #If(dbg_addr == 0b11, # MSR
723 # Display(" msr: %016x", dbg_dout),
725 If(dbg_addr
== 0b1000, # CR
726 Display(" cr : %016x", dbg_dout
),
728 If(dbg_addr
== 0b1001, # XER
729 Display(" xer: so %d ca %d 32 %d ov %d 32 %d",
730 xer_so
, xer_ca
, xer_ca32
, xer_ov
, xer_ov32
),
732 If(dbg_addr
== 0b101, # GPR
733 Display(" gpr: %016x", dbg_dout
),
735 # also check if this is a "stat"
736 If(dbg_addr
== 1, # requested a STAT
737 #Display(" stat: %x", dbg_dout),
738 If(dbg_dout
& 2, # bit 2 of STAT is "stopped" mode
739 dmirunning
.eq(1), # continue running
740 dmi_monitor
.eq(0), # and stop monitor mode
748 self
.sync
+= If(uptime
== 0,
749 (dmi_addr
.eq(0), # CTRL
750 dmi_din
.eq(1<<0), # STOP
756 self
.sync
+= If(uptime
== 4,
760 self
.sync
+= If(dmirunning
,
761 dmicount
.eq(dmicount
+ 1),
764 # loop every 1<<N cycles
768 self
.sync
+= If(dmicount
== 4,
769 (dmi_addr
.eq(0b10), # NIA
776 self
.sync
+= If(dmicount
== 8,
777 (dmi_addr
.eq(0), # CTRL
778 dmi_din
.eq(1<<3), # STEP
781 dmirunning
.eq(0), # stop counter, need to fire "monitor"
782 dmi_monitor
.eq(1), # start "monitor" instead
786 # limit range of pc for debug reporting
787 #self.comb += active_dbg.eq((0x378c <= pc) & (pc <= 0x38d8))
788 #self.comb += active_dbg.eq((0x0 < pc) & (pc < 0x58))
789 self
.comb
+= active_dbg
.eq(1)
793 self
.sync
+= If(active_dbg
& (dmicount
== 12),
794 (dmi_addr
.eq(0b11), # MSR
800 if cpu
== "libresoc":
801 #self.comb += active_dbg_cr.eq((0x10300 <= pc) & (pc <= 0x12600))
802 self
.comb
+= active_dbg_cr
.eq(0)
805 self
.sync
+= If(active_dbg_cr
& (dmicount
== 16),
806 (dmi_addr
.eq(0b1000), # CR
812 #self.comb += active_dbg_xer.eq((0x10300 <= pc) & (pc <= 0x1094c))
813 self
.comb
+= active_dbg_xer
.eq(active_dbg_cr
)
816 self
.sync
+= If(active_dbg_xer
& (dmicount
== 20),
817 (dmi_addr
.eq(0b1001), # XER
825 self
.sync
+= If(active_dbg
& (dmicount
== 24+(i
*8)),
826 (dmi_addr
.eq(0b100), # GSPR addr
833 self
.sync
+= If(active_dbg
& (dmicount
== 28+(i
*8)),
834 (dmi_addr
.eq(0b101), # GSPR data
840 # monitor bbus read/write
841 self
.sync
+= If(active_dbg
& self
.cpu
.dbus
.stb
& self
.cpu
.dbus
.ack
,
842 Display(" [%06x] dadr: %8x, we %d s %01x w %016x r: %016x",
856 self
.sync
+= If(active_dbg
& self
.cpu
.ibus
.stb
& self
.cpu
.ibus
.ack
&
858 Display(" [%06x] iadr: %8x, s %01x w %016x",
867 self
.sync
+= If(active_dbg
& self
.cpu
.ibus
.stb
& self
.cpu
.ibus
.ack
&
869 Display(" [%06x] iadr: %8x, s %01x r %016x",
878 # Build -----------------------------------------------------------------------
881 parser
= argparse
.ArgumentParser(description
="LiteX LibreSoC CPU Sim")
882 parser
.add_argument("--cpu", default
="libresoc",
883 help="CPU to use: libresoc (default) or microwatt")
884 parser
.add_argument("--platform", default
="sim",
885 help="platform (sim or ls180)")
886 parser
.add_argument("--debug", action
="store_true",
887 help="Enable debug traces")
888 parser
.add_argument("--trace", action
="store_true",
889 help="Enable tracing")
890 parser
.add_argument("--trace-start", default
=0,
891 help="Cycle to start FST tracing")
892 parser
.add_argument("--trace-end", default
=-1,
893 help="Cycle to end FST tracing")
894 parser
.add_argument("--num-srams", default
=5,
895 help="number of srams")
896 parser
.add_argument("--srams4k", action
="store_true",
897 help="enable 4k srams")
898 parser
.add_argument("--build", action
="store_true", help="Build bitstream")
899 args
= parser
.parse_args()
901 print ("number of SRAMs", args
.num_srams
)
902 print ("enable 4K SRAMs variant", args
.srams4k
)
904 if 'ls180' in args
.platform
:
905 soc
= LibreSoCSim(cpu
=args
.cpu
, debug
=args
.debug
,
906 platform
=args
.platform
,
907 srams_4k
=args
.srams4k
,
908 dff_srams
=args
.num_srams
)
909 builder
= Builder(soc
, compile_gateware
= True)
910 builder
.build(run
= True)
914 sim_config
= SimConfig(default_clk
="sys_clk")
915 sim_config
.add_module("serial2console", "serial")
918 soc
= LibreSoCSim(cpu
=args
.cpu
, debug
=args
.debug
,
919 platform
=args
.platform
,
920 dff_srams
=args
.num_srams
)
921 builder
= Builder(soc
, compile_gateware
= i
!=0)
922 builder
.build(sim_config
=sim_config
,
925 trace_start
= int(args
.trace_start
),
926 trace_end
= int(args
.trace_end
),
930 if __name__
== "__main__":