The project fit for Arty A7-35T
1.
install Vivado 2019.2.1
run step 5 in http://fatalfeel.blogspot.com/2013/12/chisel-design-ic-for-risc-v.html
gedit /etc/environment
~add path
/opt/Xilinx/Vivado/2019.2/bin
2.
cd $HOME
mkdir -p riscv_cpu
cd $HOME/riscv_cpu
git clone --recursive https://github.com/SpinalHDL/VexRiscv
3.
cd $HOME/riscv_cpu
git clone https://github.com/riscv/riscv-gnu-toolchain ###(no --recursive)
cd riscv-gnu-toolchain
git checkout 411d134
git submodule update --init --recursive
mkdir build
cd build
../configure --prefix=/opt/riscv32i --with-arch=rv32i --with-abi=ilp32
make -j8
note:
"I" Base Integer Instruction Set
"M" Standard Extension for Integer Multiplication and Divison
"A" Standard Extension for Atomic Instructions
"F" Standard Extension for Single-Precision Floating-Point
"D" Standard Extension for Double-Precision Floating-Point
"Q" Standard Extension for Quard-Precision Floating-point
"C" Standard Extension for Compressed Instruction
"G" combination of I, M, A, F and D.
ilp32/ilp32f/ilp32d int-32bits long-32bits pointer-32bits
lp64/lp64f/lp64d int-32bits long-64bits pointer-64bits
4.
cd $HOME/riscv_cpu/VexRiscv/src/main/c/murax/hello_world
gedit ./makefile
DEBUG=no
~change to
DEBUG=yes
SIFIVE_GCC_PACK ?= yes
~change to
SIFIVE_GCC_PACK=no
CFLAGS += -march=$(MARCH) -mabi=$(MABI) -DNDEBUG
ifeq ($(DEBUG),yes)
CFLAGS += -g3 -O0
endif
ifeq ($(DEBUG),no)
CFLAGS += -g -Os
endif
~change to
ifeq ($(DEBUG),yes)
CFLAGS += -march=$(MARCH) -mabi=$(MABI) -g -O0
else
CFLAGS += -march=$(MARCH) -mabi=$(MABI) -DNDEBUG -g -O3
endif
export PATH=$PATH:/opt/riscv32i/bin
export AR=riscv32-unknown-elf-ar
export AS=riscv32-unknown-elf-as
export CC=riscv32-unknown-elf-gcc
export CXX=riscv32-unknown-elf-g++
export LD=riscv32-unknown-elf-ld
make
https://www.mediafire.com/file/yk0j2nphbbdxr44/muraxhello_makefile
5.
run IntelliJ IDEA
open $HOME/riscv-cpu/VexRiscv
File -> Settings -> Build -> Build Tools -> Maven -> Importing
VM options for importer: -Xmx16384m
JDK for importer: 1.8
File -> Settings -> Build -> Build Tools -> sbt
Maximum heap size, MB: 16384
[checked] Automatically import this project on changes in build script files
File -> Settings -> Build -> Compiler -> Scala Compiler -> Scala Compiler Server
JVM maximum heap size, MB: 16384
JVM options: -server -Xss256m
File -> Settings -> Build -> Debugger
[checked] Friendly display of Scala collections in debugger
[checked] Do not expand Streams and Views
Collection start index: 0
Collection end index: 64
File -> Project Structure -> Project Settings -> Project
Project SDK: 1.8 (your java version)
[OK]
File -> Invalidate Caches / Restart
[Invalidate and Restart]
Build -> Rebuild Project
6.
right click [Murax_arty] in $HOME/riscv-cpu/VexRiscv/src/main/scala/vexriscv/demo/Murax.scala
select run
~generate
Murax.v
Murax.v_toplevel_system_ram_ram_symbol0.bin
Murax.v_toplevel_system_ram_ram_symbol1.bin
Murax.v_toplevel_system_ram_ram_symbol2.bin
Murax.v_toplevel_system_ram_ram_symbol3.bin
right click [GenFull] in $HOME/riscv_cpu/VexRiscv/src/main/scala/vexriscv/demo/GenFull.scala
select run
~generate
VexRiscv.v
7.
cd $HOME/riscv_cpu/VexRiscv/scripts/Murax/arty_a7
make all V=1
The artya7_makefile is a reference:
https://www.mediafire.com/file/4jgsmf0lvyyid3i/artya7_makefile
note: remove all [-notrace] in $HOME/riscv_cpu/VexRiscv/scripts/Murax/arty_a7 can see how the tcl running, I will do this job on Vivado 2019.2 GUI.
8.
cd $HOME/riscv_cpu/VexRiscv
cp -f ./src/main/c/murax/hello_world/build/hello_world.v ./app.mem
9.
open Vivado 2019.2 IDE
create new project
sources:
$HOME/riscv_cpu/VexRiscv/Murax.v
$HOME/riscv_cpu/VexRiscv/scripts/Murax/arty_a7/toplevel.v
constraints:
$HOME/riscv_cpu/VexRiscv/scripts/Murax/arty_a7/arty_a7.xdc
parts:
xc7a35ticsg324-1L
https://www.mediafire.com/file/2f6gqf0c0vubs04/ArtyA7-35T_Schematic.pdf
10.
[Run Synthesis]
right click Launch Synthesis Run
[Run Implementation]
[Generate Bitstream]
cp -f ./VexRiscv.runs/impl_1/toplevel.bit ./top_latest.bit
11. create mmi file manually
cp -f ~/riscv_cpu/VexRiscv/scripts/Murax/arty_a7/soc_mmi.tcl ~/riscv_cpu/VexRiscv/soc_mmi.tcl
gedit ~/riscv_cpu/VexRiscv/soc_mmi.tcl
~comment section
#if {![info exists mmi_file]} {
# set mmi_file "soc.mmi"
#}
~add
set mmi_file "~/riscv_cpu/VexRiscv/soc.mmi"
12. in Vivado 2019.2 IDE
[Run Implementation]
~then
Tool -> Run Tcl script: ~/riscv_cpu/VexRiscv/soc_mmi.tcl
~generate soc.mmi
https://www.mediafire.com/file/3sc547ywt6hm34o/soc_mmi.tcl
13. in terminal
cd $HOME/riscv_cpu/VexRiscv
updatemem -force --meminfo soc.mmi --data app.mem --bit ./top_latest.bit --proc dummy --out ./latest_soc_sw.bit
cp -f ./latest_soc_sw.bit ./latest.bit
14. in Vivado 2019.2 IDE
Tools -> Generate Memory Configuration File
Format: MCS
Custom Memory Size: 16
Filename: ~/riscv_cpu/VexRiscv/latest.mcs
Interface: SPIx4
Load Bitstream files: checked
Start address: 0 | Direction: up | Bitfile: ~/riscv_cpu/VexRiscv/latest.bit
Overwrite: checked
OK
~generate latest.mcs
15. in Vivado 2019.2 IDE
[Open Hardware Manager]
right side window [Hardware]
right click xc7a35t_0 -> Add Configuration Memory Device
search: s25fl128sxxxxxx0-spi-x1_x2_x4
click result name -> s25fl128sxxxxxx0-spi-x1_x2_x4
OK
refer to chapter 4.2 in https://digilent.com/reference/learn/programmable-logic/tutorials/arty-programming-guide/start
but we use s25fl128sxxxxxx0-spi-x1_x2_x4
16.
right click s25fl128sxxxxxx0-spi-x1_x2_x4 (child node of xc7a35t_0) -> Program Configuration Memory Device
Configuration file: ~/riscv_cpu/VexRiscv/latest.mcs
PRM file: (empty)
State of non-config mem I/O pins: Pull-none
Address Range: Configuration File Only
Erase, Program, Verify checked
OK
///////////////////////////add instruction///////////////////////////
1.
gedit $HOME/riscv_cpu/VexRiscv/src/main/scala/vexriscv/demo/Murax.scala
~add
cpuPlugins = ArrayBuffer(new SimdAddPlugin, //---> add this
new IBusSimplePlugin( resetVector = if(withXip)
2.
gedit $HOME/riscv_cpu/VexRiscv/src/main/c/murax/hello_world/src/main.c
~add follows after include
//by dolu
asm(".set abiname_zero, 0");
asm(".set abiname_ra , 1");
asm(".set abiname_sp , 2");
asm(".set abiname_gp , 3");
asm(".set abiname_tp , 4");
asm(".set abiname_t0 , 5");
asm(".set abiname_t1 , 6");
asm(".set abiname_t2 , 7");
asm(".set abiname_s0 , 8");
asm(".set abiname_s1 , 9");
asm(".set abiname_a0 , 10");
asm(".set abiname_a1 , 11");
asm(".set abiname_a2 , 12");
asm(".set abiname_a3 , 13");
asm(".set abiname_a4 , 14");
asm(".set abiname_a5 , 15");
asm(".set abiname_a6 , 16");
asm(".set abiname_a7 , 17");
asm(".set abiname_s2 , 18");
asm(".set abiname_s3 , 19");
asm(".set abiname_s4 , 20");
asm(".set abiname_s5 , 21");
asm(".set abiname_s6 , 22");
asm(".set abiname_s7 , 23");
asm(".set abiname_s8 , 24");
asm(".set abiname_s9 , 25");
asm(".set abiname_s10 , 26");
asm(".set abiname_s11 , 27");
asm(".set abiname_t3 , 28");
asm(".set abiname_t4 , 29");
asm(".set abiname_t5 , 30");
asm(".set abiname_t6 , 31");
//word func7 rs2 rs1 func3 rd opc
#define RISC_ADD(src1, src2, result) \
__asm__ volatile \
( \
".word ((0b0000000 << 25) | (abiname_%2 << 20) | (abiname_%1 << 15) | (0b000 << 12) | (abiname_%0 << 7) | 0b0110011) \n\t" \
: "=r"(result) \
: "r" (src1), "r" (src2) \
)
//word func7 rs2 rs1 func3 rd opc
#define SIMD_ADD(src1, src2, result) \
__asm__ volatile \
( \
".word ((0b0000011 << 25) | (abiname_%2 << 20) | (abiname_%1 << 15) | (0b000 << 12) | (abiname_%0 << 7) | 0b0110011) \n\t" \
: "=r"(result) \
: "r" (src1), "r" (src2) \
)
void main() {
unsigned int src1 = 0x11111111;
unsigned int src2 = 0x22222222;
unsigned int outputa= 0x00000000;
unsigned int outputb= 0x00000000;
RISC_ADD(src1, src2, outputa);
SIMD_ADD(src1, src2, outputb);
}
https://www.mediafire.com/file/l0xn2wpteibofa1/muraxhello_main.c
3.
refer to previous step and rebuild latest.mcs
burn latest.mcs to arty-a7-35t
trace uart log from arty-a7-35t's usb
done
///////////////////////////external jtag debug///////////////////////////
refer to:
https://github.com/SpinalHDL/openocd_riscv
https://tomverbeure.github.io/2021/07/18/VexRiscv-OpenOCD-and-Traps.html
https://ithelp.ithome.com.tw/articles/10196583
http://www.mediafire.com/view/ozh1f11zx8s2g5s/BusBlaster_jtag.png#
https://www.mediafire.com/file/2f6gqf0c0vubs04/ArtyA7-35T_Schematic.pdf
1.
~find Jtag pins and connect to BusBlaster, do not connect Vcc.
/$HOME/riscv_cpu/VexRiscv/scripts/Murax/arty_a7/arty_a7.xdc
/$HOME/riscv_cpu/VexRiscv/scripts/Murax/arty_a7/toplevel.v
2.
git config --global http.sslVerify false
apt install libtool automake libusb-1.0.0-dev texinfo libusb-dev libyaml-dev pkg-config
3.
cd /$HOME/riscv_cpu
git clone --recursive https://github.com/SpinalHDL/openocd_riscv.git
cd openocd_riscv
./bootstrap
./configure --prefix=/opt/vexocd --enable-ftdi --enable-dummy
make -j8 && make install
4. all paths are absolute
/opt/vexocd/bin/openocd -f /opt/vexocd/share/openocd/scripts/interface/ftdi/dp_busblaster.cfg -c 'set MURAX_CPU0_YAML /root/riscv_cpu/VexRiscv/cpu0.yaml' -f /opt/vexocd/share/openocd/scripts/target/murax.cfg
5.
/opt/riscv32i/bin/riscv32-unknown-elf-gdb $HOME/riscv_cpu/VexRiscv/src/main/c/murax/hello_world/build/hello_world.elf
target remote localhost:3333
set remotetimeout 60
set arch riscv:rv32
monitor reset halt
load
continue
PS: if you want to show debugging in IDE read [Kernel GUI debug] in this link
https://fatalfeel.blogspot.com/2015/12/openocd-with-eclipse-debug-kernel-of.html
///////////////////////////arty a7 35t internal usb jtag debug///////////////////////////
refer to:
https://github.com/SpinalHDL/VexRiscv/tree/master/doc/nativeJtag
1. comment [external jtag] and add between [arty internal usb jtag]
gedit $HOME/riscv_cpu/VexRiscv/src/main/scala/vexriscv/demo/Murax.scala
//add import
import spinal.lib.com.jtag.JtagTapInstructionCtrl
val io = new Bundle
{
val asyncReset = in Bool()
val mainClk = in Bool()
//val jtag = slave(Jtag()) //external jtag
val gpioA = master(TriStateArray(gpioWidth bits))
val uart = master(Uart())
val xip = ifGen(genXip)(master(SpiXdrMaster(xipConfig.ctrl.spi)))
}
case plugin : DebugPlugin => plugin.debugClockDomain
{
resetCtrl.systemReset setWhen(RegNext(plugin.io.resetOut))
//io.jtag <> plugin.io.bus.fromJtag() //external jtag
//arty internal usb jtag: start
val jtagCtrl = JtagTapInstructionCtrl()
val tap = jtagCtrl.fromXilinxBscane2(userId = 2)
jtagCtrl <> plugin.io.bus.fromJtagInstructionCtrl(ClockDomain(tap.TCK))
//arty internal usb jtag: end
}
val io = new Bundle
{
val mainClk = in Bool()
//external jtag
/*val jtag_tck = in Bool()
val jtag_tdi = in Bool()
val jtag_tdo = out Bool()
val jtag_tms = in Bool()*/
val uart_txd = out Bool()
val uart_rxd = in Bool()
val mosi = inout(Analog(Bool))
val miso = inout(Analog(Bool))
val sclk = out Bool()
val spis = out Bool()
val led = out Bits(8 bits)
}
//external jtag
/*val jtagClkBuffer = SB_GB()
jtagClkBuffer.USER_SIGNAL_TO_GLOBAL_BUFFER <> io.jtag_tck
jtagClkBuffer.GLOBAL_BUFFER_OUTPUT <> murax.io.jtag.tck*/
//external jtag
/*murax.io.jtag.tdi <> io.jtag_tdi
murax.io.jtag.tdo <> io.jtag_tdo
murax.io.jtag.tms <> io.jtag_tms*/
2. comment [external jtag] for rebuild project pass
gedit $HOME/riscv_cpu/VexRiscv/src/test/scala/vexriscv/MuraxSim.scala
val tcpJtag = JtagTcp(
//jtag = dut.io.jtag, //external jtag
jtag = null,
jtagClkPeriod = jtagClkPeriod
)
3. comment [external jtag]
gedit $HOME/riscv_cpu/VexRiscv/scripts/Murax/arty_a7/toplevel.v
//external jtag start
/*input wire tck,
input wire tms,
input wire tdi,
input wire trst,
output reg tdo,*/
//external jtag end
//assign io_gpioA_read[11:8] = {tck,tms,tdi,trst}; //external jtag
//external jtag: start
/*reg tesic_tck,tesic_tms,tesic_tdi;
wire tesic_tdo;
reg soc_tck,soc_tms,soc_tdi;
wire soc_tdo;*/
//external jtag: end
//external jtag: start
/*always @(*) begin
{soc_tck, soc_tms, soc_tdi } = {tck,tms,tdi};
tdo = soc_tdo;
end*/
//external jtag: end
Murax core (
.io_asyncReset(io_asyncReset),
.io_mainClk (clk100 ),
//external jtag: start
/*.io_jtag_tck(soc_tck),
.io_jtag_tdi(soc_tdi),
.io_jtag_tdo(soc_tdo),
.io_jtag_tms(soc_tms),*/
//external jtag: end
.io_gpioA_read (io_gpioA_read),
.io_gpioA_write (io_gpioA_write),
.io_gpioA_writeEnable(io_gpioA_writeEnable),
.io_uart_txd(serial_tx),
.io_uart_rxd(serial_rx)
);
rebuild Murax_arty
4.
cd $HOME/riscv_cpu/openocd_riscv/tcl/interface
wget https://raw.githubusercontent.com/SpinalHDL/SaxonSoc/dev-0.3/bsp/digilent/ArtyA7SmpLinux/openocd/usb_connect.cfg
wget https://raw.githubusercontent.com/SpinalHDL/SaxonSoc/dev-0.3/bsp/digilent/ArtyA7SmpLinux/openocd/soc_init.cfg
5.
gedit ./soc_init.cfg
set cpu_count $::env(SAXON_CPU_COUNT)
~change to
set cpu_count 1
~comment
/*if {$SPINAL_SIM != "yes"} {
targets saxon.cpu0
load_image software/standalone/sdramInit/build/sdramInit.bin 0x10A00000
puts -nonewline "init SDRAM .."
resume 0x10A00000
wait_halt
} else {
targets saxon.cpu0
load_image software/standalone/bootloader/build/bootloader_spinal_sim.bin 0x10A00000
puts -nonewline "init SDRAM .."
resume 0x10A00000
after 4000
halt
}*/
download:
https://www.mediafire.com/file/mv1ca94ji1rdwj0/soc_init.cfg
6.
cd $HOME/riscv_cpu/openocd_riscv
make -j8 && make install
7. run
/opt/vexocd/bin/openocd -f /opt/vexocd/share/openocd/scripts/interface/usb_connect.cfg -c 'set CPU0_YAML /root/riscv_cpu/VexRiscv/cpu0.yaml' -f /opt/vexocd/share/openocd/scripts/interface/soc_init.cfg
8.
eclipse setting for internal usb jtag debugging
https://www.mediafire.com/view/cwqifkpv4d27rgk/artya7-35t_internal_eclipse00.png
https://www.mediafire.com/view/jbd9r7f7rcc3y66/artya7-35t_internal_eclipse01.png
https://www.mediafire.com/view/fo5tlqccr8kijmg/artya7-35t_internal_eclipse02.png
https://www.mediafire.com/view/l81x5g1i4osxr3h/artya7-35t_internal_eclipse03.png
after eclipse setting then start debugging
9. usb log and usb jtag at the same time, when using agent-proxy for console log
git clone git://git.kernel.org/pub/scm/utils/kernel/kgdb/agent-proxy.git
cd agent-proxy
make
./agent-proxy 4440^4441 0 /dev/ttyUSB1,115200
10.
open another terminal
telnet localhost 4440 #now console log connect to target
demo:
https://www.mediafire.com/view/tm67r0tv1vwe4il/artya7-35t_internal_demo00.png
https://www.mediafire.com/view/iua7omk5bittf69/artya7-35t_internal_demo01.png
https://www.mediafire.com/file/ecp5jjy2n6effxc/arty_internal_jtag.mkv
///////////////////////////tutorial///////////////////////////
(a)
in /$HOME/riscv_cpu/VexRiscv/src/main/c/murax/hello_world/src/crt.S
.section .text
.global trap_entry
.align 5
The .align 5 will cause riscv gcc reserve .text to 0x0000000080000020
(b) disassembler in gdb
/opt/riscv32i/bin/riscv32-unknown-elf-gdb /$HOME/riscv_cpu/VexRiscv/src/main/c/murax/hello_world/build/hello_world.elf
(gdb) disas /r 0x80000000, 0x80000080
Dump of assembler code from 0x80000000 to 0x80000080:
0x80000000 <crtStart+0>: 37 01 00 80 lui sp,0x80000
0x80000004 <crtStart+4>: 13 01 01 0b addi sp,sp,176 # 0x800000b0
0x80000008 <crtStart+8>: e7 00 01 00 jalr sp
0x8000000c <crtStart+12>: 13 00 00 00 nop
0x80000010 <crtStart+16>: 00 00 unimp
0x80000012 <crtStart+18>: 00 00 unimp
0x80000014 <crtStart+20>: 00 00 unimp
0x80000016 <crtStart+22>: 00 00 unimp
0x80000018 <crtStart+24>: 00 00 unimp
0x8000001a <crtStart+26>: 00 00 unimp
0x8000001c <crtStart+28>: 00 00 unimp
0x8000001e <crtStart+30>: 00 00 unimp
0x80000020 <trap_entry+0>: 23 2e 11 fe sw ra,-4(sp)
(d)
asm(".set abiname_t0 , 5");
mean define abiname_t0 = 5
~and
%0 means gcc assign a available register name that save result value
(e) where is Jtag Tap IDcode
in DebugPlugin.scala
def fromJtag(): Jtag =
{
...
val jtagBridge = new JtagBridge(jtagConfig)
...
}
~then
SystemDebugger.scala of
~/.ivy2/cache/com.github.spinalhdl/spinalhdl-lib_2.11/srcs/spinalhdl-lib_2.11-1.6.0-sources.jar
class JtagBridge(c: SystemDebuggerConfig) extends Component
{
...
val jtag = ClockDomain(io.jtag.tck)(new Area
val tap = new JtagTap(io.jtag, 4)
val idcodeArea = tap.idcode(B"x10001FFF")(1)
val writeArea = tap.flowFragmentPush(system.cmd,JtagBridge.this.clockDomain)(2)
val readArea = tap.read(system.rsp.addTag(crossClockDomain))(3)
})
...
}
Tap IDcode = 0x10001FFF
in $HOME/riscv_cpu/VexRiscv/Murax.v can find
_zz_jtag_tap_tdoDr <= 32'h10001fff;
////////////////////////////////////////////////////////////////////////////////////////////////////
full source with patch download:
https://www.mediafire.com/file/b54k6dtpzulxfxn/VexRiscv.tar.gz
refer to:
1. http://fatalfeel.blogspot.com/2021/09/risc-v-on-icesugar.html
2. https://www.mcu.by/z-turn-lite-part-3
3. https://www.xilinx.com/support/documentation/sw_manuals/xilinx2019_2/ug898-vivado-embedded-design.pdf
4. https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18842458/Understanding+MEMDATA+flow+and+how+to+manually+create+MMI+file
5. https://digilent.com/reference/learn/programmable-logic/tutorials/arty-programming-guide/start
6. https://www.xilinx.com/support/documentation/sw_manuals/xilinx2016_2/ug975-vivado-quick-reference.pdf
7. https://pingu98.wordpress.com/2019/04/08/how-to-build-your-own-cpu-from-scratch-inside-an-fpga
Thanks for posting the useful information to my vision. This is excellent information.
回覆刪除JTAG