Closed ximinity closed 4 years ago
Thanks for the initial implementation! Adding ECP5 support to the generator was planned and i will help getting your it working.
@ximinity as discussed in https://github.com/enjoy-digital/litedram/pull/105 your initial PR has been merged and modified a bit to make it more generic, thanks for your work!
While doing it, the only real issue i saw is that you disabled the CPU, but the CPU is needed for the calibration. In the future, we will try to use the smallest CPU possible for that to avoid wasting resources. Could you do another test with upstream code?
@enjoy-digital Thanks for the changes and the merge!
I noticed that you changed the default toolchain target for ECP5 to diamond
for Lattice's Diamond toolchain. I use yosys/nextpnr/prjtrellis as my toolchain. If I change the toolchain in the new gen.py
it fails at the following step:
$ ./gen.py ../examples/versa_ecp5.yml
...
python3 -m litex.soc.software.mkmscimg bios.bin --little
make: Leaving directory '/home/ximin/litex/litedram/litedram/build/software/bios'
Traceback (most recent call last):
File "./gen.py", line 596, in <module>
main()
File "./gen.py", line 575, in main
vns = builder.build(build_name="litedram_core", regular_comb=False)
File "/usr/lib/python3.8/site-packages/litex/soc/integration/builder.py", line 181, in build
vns = self.soc.build(build_dir=os.path.join(self.output_dir, "gateware"),
File "/usr/lib/python3.8/site-packages/litex/soc/integration/soc_core.py", line 512, in build
return self.platform.build(self, *args, **kwargs)
File "/usr/lib/python3.8/site-packages/litex/build/lattice/platform.py", line 34, in build
return self.toolchain.build(self, *args, **kwargs)
File "/usr/lib/python3.8/site-packages/litex/build/lattice/trellis.py", line 216, in build
(family, size, speed_grade, package) = nextpnr_ecp5_parse_device(platform.device)
File "/usr/lib/python3.8/site-packages/litex/build/lattice/trellis.py", line 80, in nextpnr_ecp5_parse_device
size = device.split("-")[1]
IndexError: list index out of range
If I specifically use the litex.boards.platforms.versa_ecp5
's Platform
class then the generation works. I noticed that the nextpnr_ecp5_parse_device
function that throws the exception was modified in enjoy-digital/litex@83ad674feb21098c0e51e2d1c70dbdffb1744cd5, perhaps it is related.
@ximinity: the generated code will be the same, i just changed the toolchain as a workaround for the issue you just have. I'm planning to improve that, but you can already test the generated code in your design.
@enjoy-digital Where can I find the code that does the sdram calibration? I would like to implement this in hardware so a CPU is not strictly needed.
@rowanG077: the SDRAM initialization C headers are generated by https://github.com/enjoy-digital/litedram/blob/master/litedram/init.py and the initialization happens in https://github.com/enjoy-digital/litex/blob/master/litex/soc/software/bios/sdram.c#L963. Initializing up a SDR/DDR/DDR2 SDRAM should not be too complicated to do in pure logic, but for DDR3/DDR4 doing the read/write leveling is more complicated and using a CPU is easier does not necessarily cost more resources than the additional logic that will be needed to do it in pure logic. The best for that is to use the smallest CPU possible. Lite variant of VexRiscv is already good for that, in the future we'll probably have smaller variants or cores that we could use and switch to it will be very easy. So unless you are not going to use DDR3 and DDR4, i'm not sure it's worth doing it it in pure logic.
@enjoy-digital Is it crucial read/write leveling happens every boot? I'm kind of starved for resources on my platform so if I make a bootloader with a simple CPU that does the leveling then store the values in flash and read them out would that also be fine?
@ximinity: if the board is operated in the same conditions, it should indeed work. The calibration can also be done over a UART to Wishbone bridge when the board is connected to a Host. (https://github.com/enjoy-digital/versa_ecp5/blob/master/test/test_sdram.py) but that won't work if your FPGA is working in standalone.
@enjoy-digital
As you've said before, the soft-CPU inside the LiteDRAM core needs perform the initialization. The litedram_core
with the CPU option set exposes the serial receive and transmit pins. The serial rx and tx are then constrained to the FPGA Pins as specified in the Versa documentation. I'm new to LiteX so I'm not exactly sure what to do here in order to make initialization work. Currently I do the following:
litedram_core
in it.In other examples, such as [1], you also need to build firmware and upload it using, for example, litex_term
. Do I need to do the same here, e.g. create 'firmware' for the CPU that:
main
function.load_firmware.py
in [1].Sorry @ximinity for the delay. The standalone generator also generates the initial rom content that will calibrate the memory. When building with Yosys/Nextpnr, just make sure to provide litedram_core.v and litedram_core.init (which is the ROM contents). When loading your design, you should see the LiteX bios prompt and DDR3 calibration on the UART.
@ximinity: have you been able to do another test? If not, can you share your Versa ECP5 project so that i can do some hardware tests? @rowanG077: If you are operating your system in similar conditions, your could indeed use pre-computated levelings values.
@enjoy-digital
Sorry for the late response. I was originally planning on doing the testing for both this and the LiteEth changes at the start of this week but I've been really busy with writing a report for an assignment. The report is due tomorrow so I'm planning on doing the testing on Saturday. I'll report the test results and project samples then as well. Thanks for all the help you've been providing!
@enjoy-digital
I've tested the new changes and attached the basic example that I used. It simply wires the init_done
and init_error
to the LEDs on the Versa board. I've used the latest versions of LiteX and LiteDRAM. The only change I've made to the versa_ecp5.yml
is to use just the wishbone interface. After uploading the design to the board I get the follow output:
The example files I tested with: sdram_example.tar.gz.
It contains the generated core and some additional files. The wrapper instantiates a PLL and the LiteDRAM core and connects the result.
@ximinity: thanks for the test and files. Can you do another test with https://github.com/enjoy-digital/litedram/commit/b8339886dabc54cc40b69d081ea544c6c88b682a? The calibration was not setup correctly for ECP5 and this is probably what is causing the issue.
@enjoy-digital
I've tested the changes but the result is the same:
There are less attempts (it stops after the second try) but the amount of errors are the same.
OK thanks. Not sure i tested at this frequency on ECP5, could you try to increase to 75MHz? If it's still not working, i'll do some tests on hardware.
@enjoy-digital
Same result for 75MHz:
OK, i'll do some test on hardware. Can you also provide the .yml file you are using? It seems the MAIN_RAM size is not the expected one. (IIRC it should be 128MB with the Versa ECP5).
I've used the examples/versa_ecp5.yml
as a base, with some small modifications (only wishbone and 75MHz as the system clock). The input_clk_freq
doesn't seem to be used for the ECP5.
{
# General ------------------------------------------------------------------
"cpu": "vexriscv", # Type of CPU used for init/calib (vexriscv, lm32)
"memtype": "DDR3", # DRAM type
# PHY ----------------------------------------------------------------------
"sdram_module": "MT41K64M16", # SDRAM modules of the board or SO-DIMM
"sdram_module_nb": 2, # Number of byte groups
"sdram_rank_nb": 1, # Number of ranks
"sdram_phy": "ECP5DDRPHY", # Type of FPGA PHY
# Frequency ----------------------------------------------------------------
"input_clk_freq": 100e6, # Input clock frequency
"sys_clk_freq": 75e6, # System clock frequency (DDR_clk = 4 x sys_clk)
"init_clk_freq": 25e6, # Init clock frequency
# Core ---------------------------------------------------------------------
"cmd_buffer_depth": 16, # Depth of the command buffer
# User Ports ---------------------------------------------------------------
"user_ports": {
# "axi_0" : {
# "type": "axi",
# "id_width": 32,
# },
"wishbone_0" : {
"type": "wishbone",
}
# "native_0" : {
# "type": "native",
# },
# "fifo_0" : {
# "type": "fifo",
# "base": 0x00000000,
# "depth": 0x01000000,
# },
},
# CSR Port -----------------------------------------------------------------
"csr_expose": "False", # Expose CSR bus as I/Os
"csr_align" : 32, # CSR alignment
}
@ximinity: sorry for the delay, i wanted to look at it but i'm having trouble compiling the example design you provided with up to date Yosys/Trellis/Nextpnr:
ERROR: timing analysis failed due to presence of combinatorial loops, incomplete specification of timing ports, etc.
Would you mind checking it compiles with up to date tools and eventually update it if not? Thanks.
@enjoy-digital
I was able to replicate the issue with new versions of yosys/nextpnr/trellis. I've updated my toolchain to the following commits:
It seems there was an issue with the flags that I passed to yosys. I've added the updated example: sdram_example.tar.gz. The only thing you should need to modify is the sdram_example/wrapper.ys
file. The read_verilog
calls contain some absolute paths for my system.
Ok thanks. I'll look at that on next monday.
I did some changes to litedram_gen (https://github.com/enjoy-digital/litedram/commit/d4d9ab740e873a4b14b8a3a015445fbc8652fbf2, https://github.com/enjoy-digital/litedram/commit/f6babda6831277976018f734610a24d1cf648f46) and with the attached project it's working but not reliably: some initialization are failing, some are working while we don't have this behavior with the LiteX targets. I'll stop for today on this, but will have another look in the next days. Could you do some tests on your side to see if you have the same behaviour?
Here is a log of both cases:
__ _ __ _ __
/ / (_) /____ | |/_/
/ /__/ / __/ -_)> <
/____/_/\__/\__/_/|_|
Build your hardware, easily!
(c) Copyright 2012-2020 Enjoy-Digital
(c) Copyright 2007-2015 M-Labs
BIOS built on Mar 26 2020 17:18:24
BIOS CRC passed (7fafd584)
Migen git sha1: 3f9809b
LiteX git sha1: 4abb3715
--=============== SoC ==================--
CPU: VexRiscv @ 50MHz
ROM: 24KB
SRAM: 4KB
L2: 0KB
MAIN-RAM: 16384KB
--========== Initialization ============--
Initializing SDRAM...
SDRAM now under software control
Read leveling:
m0, b0: |11100000| delays: 01+-01
best: m0, b0 delays: 01+-01
m1, b0: |11100000| delays: 01+-01
best: m1, b0 delays: 01+-01
SDRAM now under hardware control
Memtest bus failed: 2/256 errors
Memtest data failed: 524282/524288 errors
Memtest addr failed: 32/8192 errors
Memory initialization failed
--============= Console ================--
litex>
__ _ __ _ __
/ / (_) /____ | |/_/
/ /__/ / __/ -_)> <
/____/_/\__/\__/_/|_|
Build your hardware, easily!
(c) Copyright 2012-2020 Enjoy-Digital
(c) Copyright 2007-2015 M-Labs
BIOS built on Mar 26 2020 17:18:24
BIOS CRC passed (7fafd584)
Migen git sha1: 3f9809b
LiteX git sha1: 4abb3715
--=============== SoC ==================--
CPU: VexRiscv @ 50MHz
ROM: 24KB
SRAM: 4KB
L2: 0KB
MAIN-RAM: 16384KB
--========== Initialization ============--
Initializing SDRAM...
SDRAM now under software control
Read leveling:
m0, b0: |11100000| delays: 01+-01
best: m0, b0 delays: 01+-01
m1, b0: |11100000| delays: 01+-01
best: m1, b0 delays: 01+-01
SDRAM now under hardware control
Memtest OK
Memspeed Writes: 202Mbps Reads: 141Mbps
--============== Boot ==================--
Booting from serial...
Press Q or ESC to abort boot completely.
sL5DdSMmkekro
Timeout
No boot medium found
--============= Console ================--
litex>
@enjoy-digital I can confirm the same behavior, though a successful memtest is very rare. The memtest bus/data/addr section now also give different results each run.
@ximinity: thanks for confirming this. We don't have this behaviour when built directly with LiteX, i'll try to understand.
With the recent changes and upstream repositories, the issue is no longer occurs. This has been tested with previous sdram_example_2020_03_26.zip
and regenerated controller.
I would like to use the LiteDRAM core as a standalone core within my designs. I'm using the Versa ECP5-5G board as my development platform. This repository contains a
gen.py
file that exists to perform exactly these steps. However, only the Xilinx-7 series of FPGAs are currently supported. I would like to add ECP5 support to this generator.I've looked at the versa_ecp5 repository to see how to instantiate the core. I've tried to add the LiteDRAM configuration in that repository to the
gen.py
generator. The verilog that is generated synthesizes using yosys/nextpnr/prjtrellis and can be flashed to the FPGA using openocd. However, theinit_done
andinit_error
are never asserted.105 is a WIP implementation for the ECP5 generator. I've added an extra configuration in the examples directory for the ECP5. It can be invoked in the same way as the other configurations:
gen.py ../examples/versa_ecp5.yml
.Aside from the generator changes I would like to ask why the
init_done
andinit_error
signals are never asserted and what actions need to be performed for this work (in the case of a standalone core).