”soc-lm32のその後2”でLatticeMico32プロセッサのコンパイラの準備ができたので、DDRに4つWriteしてから、4つReadするようにCプログラムを書き換えて、シミュレーションしてみた。(元のブートローダ・プログラムはすべてのDDR SDRAMにWriteしてから、すべてReadしていた)
そうすると、自分で書いたWishBoneバスのインターフェースがおかしくて、wb_ack_oが出力されていなかった。これを修正して、WishBoneバスのプロトコルとしては正常になったが、今度はデータが1クロック遅れている。
何でと思ったら、非同期FIFOがFWFTモードでなかったのが原因だった。Coregenをあげて、もう一度見てみると、分散RAMの非同期FIFOはFWFTモードが選べなかった。
以前、
”Virtex4のFIFO(FWFTモード)”でやってみた時は、Fifo Generator 2.3 のSpartan3で、BlockRAMと分散RAMのFWFTモードのFIFOをジェネレートできたようだ。しかし、ISE10.1iのFifo Generater 4.4 (Spartan3E) の分散RAMを使用した非同期FIFOでは、FWFTモードが選べない。
FWFTモードが選べないのはしょうがないので、データの出力イネーブルを1クロック遅らせた。
これでハード的には大丈夫なはず。。。

もう一度、ブートローダのmコマンド(memtest) をすべてのDDR SDRAMをテストするように戻してからインプリメントして、やってみたところ、まだMEMTEST ERROR が出てしまっている。どんな風に間違っているのかを調べるために v コマンドでDDR SDRAMのデータを見たら、0x40000000 であるはずのデータが 0x42000000 になっている。以下、同様になっていた。

これはおかしいと思った。もしやソフトウェアが間違っているのかも?どうも4回りしているような気がする。
soc-lm32/firmware/bootloader/spike_hw.h を見ると
#define RAM_SIZE 0x04000000
と書いてあったが、Spartan3E Starter Kit についてる DDR SDRAM (
MT46V32M16P-6T) は512Mbit なので、バイトにすると 64Mbyte なので、0x04000000 であっているはず。
soc-lm32/firmware/bootloader/main.c の memtest.c 一部を下に引用する。
void memtest()
{
volatile uint32_t *p;
uart_putstr("\r\nMEMTEST...");
for (p=(uint32_t *)RAM_START; p<(uint32_t *)(RAM_START+RAM_SIZE); p++) {
*p = (uint32_t) p;
}
(uint32_t *)(RAM_START+RAM_SIZE)
のところで、RAM_SIZEを足した後に、
uint32_t * でキャストをすると4倍になってしまうと思ったので、ここを、(uint32_t *)(RAM_START+RAM_SIZE/(sizeof(uint32_t *)))
に変更した。これでインプリメントして、m コマンドを入れてみたらOKとなった。v コマンドで内容を見ても、大丈夫そうだった。

これで、DDR SDRAMもOKとなった。。。自分で作ったDDR SDRAMコントローラIPの動作が確認できて、とてもうれしい。実際に、プロセッサのメモリとして動いているのを見ると、感慨もひとしおだ。
いよいよ、uCLinuxを勉強しながら、ダウンロードスピードを増すために、UARTのビットレートアップを図っていこうと思う。
2008/10/14:追加 くりさんのご指摘で考え直したところ、(uint32_t *)(RAM_START+RAM_SIZE) はそのままで良いという結論になりました。ということは私の作ったDDR SDRAMコントローラの最上位アドレス2ビットの扱いがおかしいということになります。もう一度、この近辺をデバックします。とりあえず、それ以外は動いているので、すぐデバックできると思います。
くりさん、ご指摘ありがとうございました。勘違いしていました。
2008/10/14:追加2
DDR SDRAMコントローラの最上位アドレス2ビットの扱いがおかしい訳ではなく、バイトアドレスのWishBoneバスのアドレスを、RAMチップデータ幅単位(2バイト)のDDR SDRAMコントローラのアドレスにそのまま入れていたのが原因でした。
つまり、WishBoneバスのアドレスをDDR SDRAMコントローラに入れるところの非同期FIFOの入力を
async_fifo_addr async_fifo_addr_inst (
.din({wb_r_w, wb_adr_i}),
から、これに
async_fifo_addr async_fifo_addr_inst (
.din({wb_r_w, 1'b0, wb_adr_i[31:1]}),
に変更したところ、元のソフトウェアでOKとなりました。
お騒がせして申し訳ありません。。。
- 2008年10月13日 19:01 |
- Spartan3E Starter Kit でマイコンを作る
-
| トラックバック:0
-
| コメント:2
こんばんわ。
>RAM_SIZEを足した後に、uint32_t * でキャストをすると4倍になってしまうと思ったので
うーんと、この場合、キャスト自体が4倍(=スケーリング)することはないというか、あるとすれば RAM_START+RAM_SIZE の加算時ですが、それには RAM_START が4バイトのポインタとして宣言されていることが必要です。もし、RAM_STARTも #define などで定義された単なる整数定数の場合は、計算は(RAM_START+RAM_SIZE)が整数加算として優先され、しかる後、加算値が整数型からポインタ型に変換されます。この場合、単にコンパイラが文句を言わないように、内部の宣言型が調整されるだけで、数値はそのままの値が使われることになるはずです。もしコンパイラ出力に疑問を感じた場合は、objdump等で逆アセンブルし、コードを直接確認するのが、もっとも確実な方法です。まあ、objdumpにもバグがあれば・・・ですが。
- 2008/10/13(月) 23:22:55 |
- URL |
- くり #mQop/nM.
- [ 編集 ]
くりさん、ご指摘ありがとうございました。
ブログ記事を修正しました。もう一度、DDR SDRAMコントローラをデバックします。
- 2008/10/14(火) 04:55:01 |
- URL |
- marsee #-
- [ 編集 ]