OpenRISC とは、RTL (Register Transfer Level) の Verilog-HDL が公開されている 32 bit RISC CPU です。 gcc, binutils も移植され、uClinux なども動作しています。 OpenCores で配布されています。
ここでは配布されている Tutorial に沿って OpenRISC の構築方法を説明します。 具体的には、Altera の FPGA 上に OpenRISC を合成して、クロス開発環境を構築して、サンプルプログラムをコンパイルして、メモリに配置して実行します。 ただし、Tutorial と同じ環境が手に入らなかったので、ハードウェア構成やプログラムのローディング方法が Tutorial とは異なります。
OpenRISC is an open-source 32-bit RISC CPU written in Verilog, and distributed from OpenCores [opencores.org]. GCC and Binutils have been ported for the processor. uClinux also works on it. Here, I explain how to configure OpenRISC along with a distributed tutorial. The explanation includes synthesizing OpenRISC on Altera FPGA, building cross development environment, compiling a sample program, and running the program allocated on memory. Although, I was not able to obtain the same environment as the tutorial, the hardware configuration and the way to load a program are different from the tutorial.
動作環境
- 評価ボード: 三菱電機マイコン機器ソフトウェア MMS PowerMedusa MU200-AP AP1500
- FPGA: Altera APEX2KE EP20K1500EBC652
- FPGA開発環境: Altera Qaurtus II version 4
- RTL開発環境: Cadence Verilog-XL 04.10.001-p (そのまま合成するならば必ずしも必要ないですが、変更を加える場合は RTL simulation 無しでは辛いです。)
- Host PC: Windows (for Quartus II), Debian GNU/Linux sid (for gcc, binutils)
以下では、"Basic Custom OpenRISC System Hardware Tutorial (Altera)" の流れに沿って説明しますが、Tutorialとは違う方法で実装している部分も多いです。 Tutorial中で利用しているデバイスはStratixでしたが、手元にあるデバイスはAPEXです。 Stratixのメモリ(altsyncram)とAPEXのメモリ(lpm_ram_dq)ではbyte enableなど制御線が異なっているので、Tutorialの通りには配線できません。 また、評価ボードもTutorialと手元にあるものとは異なっています。 Tutorialではプログラムダウンロードやデバッグのため、JTAGケーブルを利用しています。 Tutorialで利用しているボードではFPGAのconfiguration用JTAG pin以外に、 FPGA内部のOpenRISC CPUのconfiguration用JTAG pinをFPGAのuser pinに割り当てXilinxのJTAGケーブルに接続しています。 手元のボードでOpenRISC用JTAG pinを用意できなかったので、プログラムをJTAGでダウンロードするのではなく、Memory Initialization File (.mif) Description を利用して、 FPGA内部のSRAMの初期値としてプログラムをロードすることにしました。 こうすることで、user pinをJTAGに割り当ててdownloadしなくてもプログラムを実行できます。ただし、Quartus IIでの合成時にあらかじめプログラムをコンパイルし、MIFに変換しておく必要がありますので、プログラムを頻繁に入れ替えるには適していません。 そのような場合は、モニタプログラムをMIFで配置し、モニタプログラムでRS232CなどからRAMにプログラムを展開し実行するのが妥当だと思います。モニタは自作しないとなりませんが…。
OpenRISC Reference Platform (ORP) をダウンロードします。cvs コマンドでなく ORPsoc のCVSgetでdownloadしました。
$ tar zxvf or1k_orp_orp_soc.tar.gz
or1k/orp/orp_soc/rtl/verilog 以下
ディレクトリ audio, ethernet, ethernet.old, or1200.old, ps2, ps2.old, svga, uart16550.old と、 ファイルtdm_slave_if.v を削除
``define TARGET_VIRTEX` をコメントアウト
``include bench_defines.v` をコメントアウト
module xsv_fpga_top1 part
2 global signals (clk, rstn)
2 uart signals (uart_stx, uart_srx)
7 jtag debug signals (jtag_tvref, jtag_tgnd, jtag_tck, jtag_tms, jtag_trst, jtag_tdi, jtag_tdo)
を残す。
input and output list
7 input: clk, rstn, uart_srx, jtag_tck, jtag_tms, jtag_trst, jtag_tdi
4 output: uart_stx, jtag_tvref, jtag_tgnd, jtag_tdo
を残す。
internal wires list
Debug core master i/f wires, Debug <-> RISC wires, RISC instruction master i/f wires, RISC data master i/f wires, RISC misc, SRAM controller slave i/f wires, UART16550 core slave i/f wires, UART external i/f wires, JTAG wires
を残す。
assign part
TutorialではPLLを用いて分周するが、手元のボードではFPGA外部分周器で10MHzの入力が可能なので、PLLは省略。
つまり、assign wb_clk = clk;はそのまま残す。
SRAM tri-state data, Ethernet tri-state, PS/2 Keyboard tri-state, Unused interrupts, RISC Instruction address for Flashは削除
Unused WISHBONE signalsは assign wb_us_err_o = 1'b0;だけ残す。
必要ならば、jtag_tvrefとjtag_tgndをVdd/GNDに固定
assign jtag_tvref = 1'b1;
assign jtag_tgnd = 1'b0;
instantiations part
Instantiation of the VGA CRT controller, Instantiation of the Audio controller, Instantiation of the Flash controller, Instantiation of the Ethernet 10/100 MAC, Instantiation of the PS/2 Keyboard Controller, Instantiation of the CPLD TDM
を削除。 残った、instantの宣言を修正
or1200_topのwb_clkをclkに変更PLLを使わないのでwb_clkを繋げたままにしておく。- or1200_topの最後の接続.pic_ints_iのpic_intsを20'b0に変更
sram_top sram_topをonchip_ram_top onchip_ram_topに変更- onchip_ram_top (sram_top) の // SRAM external 以下を削除
- uart_topの
.int_o(pic_ints[APP_INT_UART])を.int_o()` に変更 - Traffic cop インスタンスを以下のように修正
- MASTERS: Wishbone Initiatorの 0, 1, 2 を stub (Initiator 6, 7のよう)に置き換え
- SLAVES: Wishbone Target 1, 2, 3, 4, 6を stub (Target 7, 8のよう)に置き換え
.i4_wb_ack_o(wb_rdm_ack),を.i4_wb_ack_o(wb_rdm_ack_i),に置き換え.i5_wb_adr_i(wb_rif_adr),を.i5_wb_adr_i(wb_rim_adr_o),に置き換え
以上の修正を加えた xsv_fpga_top.v
- Enable ``define OR1200_ALTERA_LPM`
- Disable ``define OR1200_XILINX_RAMB4`
- Enable
define OR1200_NO_DC`,define OR1200_NO_IC, ``define OR1200_NO_DMMUand ``define OR1200_NO_IMMU` - Disable ``define OR1200_CLKDIV_2_SUPPORTED`
- Disable ``define OR1200_RFRAM_DUALPORT`
- Enable ``define OR1200_RFRAM_GENERIC`
- Disable ``define OR1200_DU_TB_IMPLEMENTED
or1200/or1200_cpu になっていて、最初から .genpc_stop_prefetch(1'b0) になっていました。
FPGA外部の分周回路で10MHzのクロックを生成しFPGAに入力するため、省略しました。
ここがORPにもTutorialにも含まれていない部分で苦労したところです。 TutorialではStratixを利用しているため、RAMはaltsyncramを利用します。 しかし、手元にあるデバイスはAPEXだったので、altsyncramは利用できません。 そこで入出力や動作がaltsyncramに似たものを作成できるlpm_ram_dqを利用しました。
StratixとAPEXはいろいろ違いはありますが、今回の一番の違いbyte enable信号の対応・未対応です。 altsyncramはbyte enable信号に対応していますが、lpm_ram_dqは対応していません。 OpenRISCはbyte accessがあり、Wishbone busのselect信号を利用するので、memoryにはbyte enable信号が必要です。 そこで、lpr_ram_dqを4つのbankに分割して作成し、byte enable信号をそれぞれのbankのwrite enableにデコードしました。
MIF Fileを呼んでいるので、onchip_ramをおいたdirectoryにonchip_ram_bank[0-3].mifを配置してください。 RTL simulationのための記述を含みます。`ifdefで分けてありますので、Quartus IIの合成では無視されます。
この手順に進む前に、onchip_ramの初期値 (MIF file)を用意しておく必要があります。 Softwareの項を先に読んで下さい。
- Start Quartus II
- Create a new quartus project
- Select a directory
- Select the source files
or1k/orp/orp_soc/rtl/verilog/以下で、 dbg_interface/dbg_.v, or1200/or1200_.v, uart16550/uart_*.v, uart16550/raminfr.v, xsv_fpga_top.v, xsv_fpga_defines.v, tc_top.vを選択します。
また、onchip RAM component (onchip_ram.vとonchip_ram_bank[0-3].mif)を選択します。 onchip_ram_bank[0-3].mifについてはSoftware Tutorialで後述します。 MIFにあらかじめプログラムを記述するために、合成まえにプログラム開発環境を整えて、プログラムコンパイルしておく必要があります。 - include the library path names
- design entry synthesis tool
- select target family
- target component
- finish
- pin assign xsv_fpga_topの入出力pinを直接FPGAのpinにassignしてもいいのですが、 いつも評価ボード用のVerilog-HDLファイルを用意しているので、その中でxsv_fpga_topを呼び出します。 こうすることとで、pin assigmentをproject毎に再設定する必要がなくなります。
xsv_fpga_top xsv_fpga_top(OSC, RESET, RD1_OUT, TD1_IN, jtag_tvref, jtag_tgnd, jtag_tck, jtag_tms, jtag_trst, jtag_tdi, jtag_tdo);今回はOpenRISC用のJTAGを利用しないので、debugモジュールをdisableにしておかないとなりません。 そこで、そのxsv_fpga_topを呼んでいる一番top levelのverilogでJTAGのpinの処理をしました。
wire jtag_tck; assign jtag_tck = 0; wire jtag_tdo; // NC assign jtag_tdo = 1'bz; wire jtag_tms; assign jtag_tms = 0; wire jtag_tdi; assign jtag_tdi = 0; wire jtag_tvref; // NC assign jtag_tvref = 1'bz; wire jtag_tgnd; // NC assign jtag_tgnd = 1'bz; wire jtag_trst; assign jtag_trst = 0; // 1?- compilation
Fitterの結果を引用します。
+---------------------------------------------------------------+ ; Fitter Summary ; +-----------------------+---------------------------------------+ ; Fitter Status ; Successful - Fri Jul 09 10:56:02 2004 ; ; Revision Name ; xsv_fpga_top ; ; Top-level Entity Name ; mu200 ; ; Family ; APEX20KE ; ; Device ; EP20K1500EBC652-3 ; ; Total logic elements ; 10,237 / 51,840 ( 19 % ) ; ; Total pins ; 275 / 488 ( 56 % ) ; ; Total memory bits ; 196,864 / 442,368 ( 44 % ) ; ; Total PLLs ; 0 / 4 ( 0 % ) ; +-----------------------+---------------------------------------+評価ボードとPCをRS232Cで接続し、シリアルターミナルを9600bpsで接続しておきます。 JTAGを接続して、*.sofをFPGAにdownloadします。 downloadが終ると自動的にreset vectorにおいたプログラムを実行開始します。 ターミナルに、"Hello World!"と表示されれば成功です。
"Basic Custom OpenRISC system Software Tutorial"を参考に、Debian GNU/Linux sid上で、 クロス開発環境、サンプルプログラム、実行バイナリ(Motorola S format)からMIFへの変換プログラムを用意しました。
gcc (クロス開発環境をコンパイルするためのコンパイラ) Tutorialではホスト用のgccは2.95.x or 2.96が必要と書かれていますが、とりあえず既存の環境で構築してみました。
$ gcc -v gcc version 3.3.4 (Debian 1:3.3.4-2)ただし、Debian sid (unstable)では、flexが新しすぎてクロスコンパイラ用のgccをうまくコンパイルできなかったので、flexはstable版に戻しました。
$ flex --version flex version 2.5.31 # apt-get remove flex # apt-get install flex/stable $ flex --version flex version 2.5.4CVSからsourceを取得。
$ export CVSROOT=:pserver:anonymous@cvs.opencores.org:/cvsroot/anonymous $ cvs login $ cvs -z9 co or1k/binutils $ cvs -z9 co or1k/gcc-3.2.3 $ cvs -z9 co or1k/gdb-5.0 $ cvs -z9 co or1k/hello-uartbinutils-2.11.93
$ export LANG=C $ cd or1k; mkdir b-b; cd b-b $ ../binutils/configure --target=or32-uclinux $ make # make installgcc-3.2.3
$ cd ../or1k; mkdir b-gcc; cd b-gcc; $ ../gcc-3.2.3/configure --target=or32-uclinux --with-gnu-as \ --with-gnu-ld --verbose --enable-languages=c $ make # make installgdb-5.0
$ cd ../or1k; mkdir b-gcc; cd b-gcc; $ ../gdb-5.0/configure --target=or32-uclinux $ make # make installRS232Cに"Hello World!"を出力するサンプルプログラムをコンパイルします。
or1k/hello-uart/board.hを修正
clock 10MHz, RS232C 9600bps
#define IN_CLK 10000000 #define STACK_SIZE 0x1000 #define UART_BAUD_RATE 9600 #define UART_BASE 0x90000000 #define REG8(add) *((volatile unsigned char *)(add)) #define REG16(add) *((volatile unsigned short *)(add)) #define REG32(add) *((volatile unsigned long *)(add))- or1k/hello-uart/ram.ld を修正
ram : ORIGIN = 0x00002000, LENGTH = 0x00002000- make
- Makefile
or1k/hello-uart/Makefileと入れ替え - srec2mif.pl
srec (Motorola S format)からMIF fileを生成するPerl script。or1k/hello-uart/に入れる - srec2rtl.pl srec (Motorola S format)からonchip_ram.vからincludeされるRTL記述を生成する Perl script。 合成するだけならばRTL simulationはしないので要らない。 or1k/hello-uart/に入れる。
- Makefile
$ cd ../or1k/hello-uart $ make or32-uclinux-gcc -g -c -o reset.o reset.S -Wa,-alnds=reset.log or32-uclinux-gcc -g -c -o hello.o hello.c -Wa,-alnds=hello.log or32-uclinux-ld -Tram.ld -o hello.or32 reset.o hello.o or32-uclinux-objcopy -O srec hello.or32 hello.srec or32-uclinux-objcopy -O ihex hello.or32 hello.ihex or32-uclinux-objdump -S hello.or32 > hello.S ./srec2mif.pl hello.srec ./srec2rtl.pl hello.srec生成された onchip_ram_bank[0-3].mif (MIF file), onchip_ram_bank[0-3].v (RTL simulation用) を onchip_ram.v と同じdirectoryに移動 (symbolic linkしておくと便利)。 MIFの準備ができたので、Quartusでの合成手順に進む。
- OpenRISC
- OpenRISC 1000 Architecture Manual
- OpenRISC 1000: GNU Toolchain Port
- Tutorials Resarch Group Digital Techniques, Hogeschool voor Wetenschap & Kunst.
- Basic Custom OpenRISC System Hardware Tutorial (Altera)
- Basic Custom OpenRISC System Hardware Tutorial (Xilinx)
- Basic Custom OpenRISC system Software Tutorial
- OR1K uClinux and simulator installation
