Navre AVR clone

「Navre AVR clone」の編集履歴(バックアップ)一覧はこちら

Navre AVR clone」(2013/11/12 (火) 15:05:24) の最新版変更点

追加された行は緑色になります。

削除された行は赤色になります。

長々とステートマシンを記述するのは苦手で、処理の変更も簡単にできるよう、 ステートマシンの代わりに、ソフトプロセッサを使用することにした。 FPGAに複数積むので、小型であること。ソフトウェアの開発が簡単にできるよう、gcc対応であることを条件に、 OpenCoresで探したところ、Navre AVR clone(正確にはNavré AVR clone)を見つけたので、 調べたことの備忘録としてこのページにまとめる。 *Navre AVR cloneとは -http://opencores.org/project,navreで公開されているAVRコンパチブルのソフトプロセッサ -記述言語はVerilog -周辺回路や割り込み、スリープは実装されていない -命令セットは、http://en.wikipedia.org/wiki/Atmel_AVR_instruction_setの&br()Instruction set inheritanceの項目のClassic Core up to 8K Program Spaceまで対応のようだ -無条件分岐のIJMP命令(アドレスを16bitで指定)は対応しているが、&br()JMP命令(アドレスを22bitで指定)は対応していないようなのでプログラムは64Kwordまでのようだ -本来のAVRでは、データ空間にレジスタ・IOもマッピングされてるが、&br()ソースファイルを見たところ、NavreAVRではデータ空間に他のものがマッピングされておらず別々のものとして使ってるみたい? --つまり、データ空間はアドレス幅そのままの64Kbyte全て使えるかも? -IO空間は64byteしか無いけどIN・OUT命令では、IO空間のアドレス幅は6bitまでなので、それ以上に拡張することはできないかも? --IO空間が足りなければデータ空間にマッピングすればいいか?(本家AVRはそうなってるらしい) *ソフトウェアの開発 AtmelStudioを入れても、実際使うのはコンパイルに必要な物だけなので、無駄が多い。 また、メモリの容量などは実際のAVRとは違うものになるため、自分でリンカスクリプトを書くことになる。 → AVR Toolchainをインストールしてコマンドラインで開発したほうがよさそう **AVR Toolchainのインストール 公式サイトからDL&インストール パスは自動で通してくれるので、すぐ使える **ソフト設計・コーディング 普通のAVRとだいたい同じだと思う **ビルド 参考:http://www.clarestudio.org/elec/avr/gcc-1.html ビルドする簡単な手順はおそらく以下のようになる。 対応している命令を指定するため、「-mmcu=avr2」オプションを追加している。 #highlight(none){{{ avr-gcc -mmcu=avr2 -c hoge.c // コンパイル avr-gcc -mmcu=avr2 -o hoge.elf hoge.o // リンク avr-objdump -d hoge.elf > hoge.dump // 機械語とアセンブリのリスト出力 avr-objcopy -I elf32-avr -O ihex hoge.elf hoge.hex // ELFファイルをIntelHex形式に変換}}} ビルドしたプログラムが、メモリに載る容量か確認 #highlight(none){{{ avr-size hoge.elf}}} その後、FPGA内蔵メモリブロックの初期値としてプログラムを読み込むために IntelHexファイルを$readmemhシステムタスク用に変換 #highlight(none){{{ avr-objcopy -I ihex -O verilog hoge.hex hoge_memh.txt cat hoge_memh.txt $ cat hoge_memh.txt @00000000 0C C0 13 C0 12 C0 11 C0 10 C0 0F C0 0E C0 0D C0 0C C0 0B C0 0A C0 09 C0 08 C0 11 24 1F BE CF E5 D2 E0 DE BF CD BF 02 D0 35 C0 EA CF CF 93 DF 93 ...}}} objcopyの出力する初期化ファイルのフォーマットは、バイトごとに空白で区切られているため、 $readmemhでそのまま読むと、ROMの上位16ビットはゼロで、下位16ビットに1バイトごと格納されてしまう。 AVRは1word=16bitなので、2バイトごとつなげて改行(あるいは空白)を入れるようにしなければいけない。 さらに、AVRはリトルエンディアンなので、バイトごとに前後入れ替えて繋げなければならない。 ちょうど同じことをするスクリプトを公開している方がいらっしゃったため、それを使わせてもらった。 http://www.koka-in.org/~kensyu/handicraft/diary/20110427.htmlのbyte2xst.pl #highlight(none){{{ perl byte2xst.pl 2048 < hoge_memh.txt > test_memh_conv.txt cat test_memh_conv.txt C00C C013 C012 C011 C010 C00F ...}}} あとは、VerilogのROM用コードを以下のようにすればFPGAに回路がロードされた時、プログラムがブロックメモリに置かれる 参考:[[Altera Recommended HDL Coding Styles>http://www.altera.com/literature/hb/qts/qts_qii51007.pdf]]のExample 14–26. Verilog HDL RAM with Initialized Contents と Example 14–27. Verilog HDL RAM Initialized with the readmemb Command #highlight(none){{{ module ram_with_init #( parameter depth = 11, parameter width = 16 ) ( output reg [width-1:0] q, input wire [width-1:0] d, // ROMの場合不要 input wire [depth-1:0] a, input wire we, // ROMの場合不要 input wire clk ); reg [width-1:0] mem [0:(1<<depth)-1]; initial begin $readmemh("C:\projdir\hoge_memh.txt", mem); end always @ (posedge clk) begin if (we) // ROMの場合不要 mem[a] = d; // ROMの場合不要 q = mem[a]; end endmodule}}} &bold(){$readmemhでのファイル指定は、フルパスでないとシミュレーション時にModelSimが初期化してくれない。&br()改善方法知ってる方がいたら教えてくださると助かります。} *テクニック **変数を配置するアドレスを固定する 参照:http://stackoverflow.com/questions/4067811/how-to-place-a-variable-at-a-given-absolute-address-in-memory-with-gcc FPGAに載せるプロセッサということで、複数のNavreAVRcloneを止めて一斉にRAMの中身を外部から読み書きするということを しなければならない事があった。(本来はこんなトリッキーな手法を使うべきではないかもしれないが・・・) そのため、読み書きする対象の変数のアドレスを固定しなければならない。 その方法は、 #highlight(none){{{ int *hoge_p = (int*)0x400; #define hoge *hoge_p // 普通の変数と同じように扱えるように名前変更 hoge = 4;}}} とすることで解決した。 はじめは、ARMのドキュメントで見つけた #highlight(none){{{ __attribute__((at(0x400)))}}} と属性を付けてやる方法がスマートで良さそうだと考えていたが、 avr-gccでは対応していないようだ。 そのため、上記のような方法で宣言することになった。
長々とステートマシンを記述するのは苦手で、処理の変更も簡単にできるよう、 ステートマシンの代わりに、ソフトプロセッサを使用することにした。 FPGAに複数積むので、小型であること。ソフトウェアの開発が簡単にできるよう、gcc対応であることを条件に、 OpenCoresで探したところ、Navre AVR clone(正確にはNavré AVR clone)を見つけたので、 調べたことの備忘録としてこのページにまとめる。 *Navre AVR cloneとは -http://opencores.org/project,navreで公開されているAVRコンパチブルのソフトプロセッサ -記述言語はVerilog -周辺回路や割り込み、スリープは実装されていない -命令セットは、http://en.wikipedia.org/wiki/Atmel_AVR_instruction_setの&br()Instruction set inheritanceの項目のClassic Core up to 8K Program Spaceまで対応のようだ -無条件分岐のIJMP命令(アドレスを16bitで指定)は対応しているが、&br()JMP命令(アドレスを22bitで指定)は対応していないようなのでプログラムは64Kwordまでのようだ -本来のAVRでは、データ空間にレジスタ・IOもマッピングされてるが、&br()ソースファイルを見たところ、NavreAVRではデータ空間に他のものがマッピングされておらず別々のものとして使ってるみたい? --つまり、データ空間はアドレス幅そのままの64Kbyte全て使えるかも? -IO空間は64byteしか無いけどIN・OUT命令では、IO空間のアドレス幅は6bitまでなので、それ以上に拡張することはできないかも? --IO空間が足りなければデータ空間にマッピングすればいいか?(本家AVRはそうなってるらしい) *ソフトウェアの開発 AtmelStudioを入れても、実際使うのはコンパイルに必要な物だけなので、無駄が多い。 また、メモリの容量などは実際のAVRとは違うものになるため、自分でリンカスクリプトを書くことになる。 → AVR Toolchainをインストールしてコマンドラインで開発したほうがよさそう **AVR Toolchainのインストール 公式サイトからDL&インストール パスは自動で通してくれるので、すぐ使える **ソフト設計・コーディング 普通のAVRとだいたい同じだと思う **ビルド 参考:http://www.clarestudio.org/elec/avr/gcc-1.html ビルドする簡単な手順はおそらく以下のようになる。 対応している命令を指定するため、「-mmcu=avr2」オプションを追加している。 #highlight(none){{{ avr-gcc -mmcu=avr2 -c hoge.c // コンパイル avr-gcc -mmcu=avr2 -o hoge.elf hoge.o // リンク avr-objdump -d hoge.elf > hoge.dump // 機械語とアセンブリのリスト出力 avr-objcopy -I elf32-avr -O ihex hoge.elf hoge.hex // ELFファイルをIntelHex形式に変換}}} ビルドしたプログラムが、メモリに載る容量か確認 #highlight(none){{{ avr-size hoge.elf}}} その後、FPGA内蔵メモリブロックの初期値としてプログラムを読み込むために IntelHexファイルを$readmemhシステムタスク用に変換 #highlight(none){{{ avr-objcopy -I ihex -O verilog hoge.hex hoge_memh.txt cat hoge_memh.txt $ cat hoge_memh.txt @00000000 0C C0 13 C0 12 C0 11 C0 10 C0 0F C0 0E C0 0D C0 0C C0 0B C0 0A C0 09 C0 08 C0 11 24 1F BE CF E5 D2 E0 DE BF CD BF 02 D0 35 C0 EA CF CF 93 DF 93 ...}}} objcopyの出力する初期化ファイルのフォーマットは、バイトごとに空白で区切られているため、 $readmemhでそのまま読むと、ROMの上位8ビットはゼロで、下位8ビットに1バイトごと格納されてしまう。 AVRは1word=16bitなので、2バイトごとつなげて改行(あるいは空白)を入れるようにしなければいけない。 さらに、AVRはリトルエンディアンなので、バイトごとに前後入れ替えて繋げなければならない。 ちょうど同じことをするスクリプトを公開している方がいらっしゃったため、それを使わせてもらった。 http://www.koka-in.org/~kensyu/handicraft/diary/20110427.htmlのbyte2xst.pl #highlight(none){{{ perl byte2xst.pl 2048 < hoge_memh.txt > test_memh_conv.txt cat test_memh_conv.txt C00C C013 C012 C011 C010 C00F ...}}} あとは、VerilogのROM用コードを以下のようにすればFPGAに回路がロードされた時、プログラムがブロックメモリに置かれる 参考:[[Altera Recommended HDL Coding Styles>http://www.altera.com/literature/hb/qts/qts_qii51007.pdf]]のExample 14–26. Verilog HDL RAM with Initialized Contents と Example 14–27. Verilog HDL RAM Initialized with the readmemb Command #highlight(none){{{ module ram_with_init #( parameter depth = 11, parameter width = 16 ) ( output reg [width-1:0] q, input wire [width-1:0] d, // ROMの場合不要 input wire [depth-1:0] a, input wire we, // ROMの場合不要 input wire clk ); reg [width-1:0] mem [0:(1<<depth)-1]; initial begin $readmemh("C:\projdir\hoge_memh.txt", mem); end always @ (posedge clk) begin if (we) // ROMの場合不要 mem[a] = d; // ROMの場合不要 q = mem[a]; end endmodule}}} &bold(){$readmemhでのファイル指定は、フルパスでないとシミュレーション時にModelSimが初期化してくれない。&br()改善方法知ってる方がいたら教えてくださると助かります。} *テクニック **変数を配置するアドレスを固定する 参照:http://stackoverflow.com/questions/4067811/how-to-place-a-variable-at-a-given-absolute-address-in-memory-with-gcc FPGAに載せるプロセッサということで、複数のNavreAVRcloneを止めて一斉にRAMの中身を外部から読み書きするということを しなければならない事があった。(本来はこんなトリッキーな手法を使うべきではないかもしれないが・・・) そのため、読み書きする対象の変数のアドレスを固定しなければならない。 その方法は、 #highlight(none){{{ int *hoge_p = (int*)0x400; #define hoge *hoge_p // 普通の変数と同じように扱えるように名前変更 hoge = 4;}}} とすることで解決した。 はじめは、ARMのドキュメントで見つけた #highlight(none){{{ __attribute__((at(0x400)))}}} と属性を付けてやる方法がスマートで良さそうだと考えていたが、 avr-gccでは対応していないようだ。 そのため、上記のような方法で宣言することになった。

表示オプション

横に並べて表示:
変化行の前後のみ表示: