1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

DE0-NANOのSDRAMにNiosIIからアクセスする

Last updated at Posted at 2019-06-25

##環境

  • Terasic DE0-Nano
  • Quartus Prime 18.1 Lite Edition

奮発して「FPGAボードで学ぶ組込みシステム開発入門[Intel FPGA編]」を購入した。
本書はDE1-SoCとDE10-Liteを対象にしており、DE0-Nanoは対象にしてないが、
そこは適当に読み解きながら試す。

第8章 1節 外部SDRAMの制御

表8-3
DE1-SoCのSDRAMは64M、当方のDE0-Nanoは32MBであるため、Address Width Columを10→9に変更する。

リスト8-1
最上位層のsdram.vを変更した。おそらく本書はリセットどこかのピンにつないでるらしいが、ピンアサインは記載が無いので、DE0-NanoのMy_First_NiosII_Qsys.pdfを参考にした。

sdram.v抜粋
.reset_reset_n                     (~RST),
sdram.v抜粋
.reset_reset_n                     (1'b1),

本書にある、SDRAMの全領域にBYTE,SHORT,INTを順次書き込むテストプログラムを走らせると、たまにNGになる。

調査のため、コードを変更して以下のとおりにする。

sdram_test.c
#include "sys/alt_stdio.h"
#include "sys/alt_cache.h"
#include "system.h"

#define SDRAM_C ((volatile unsigned char *) NEW_SDRAM_CONTROLLER_0_BASE)
#define SDRAM_S ((volatile unsigned short *) NEW_SDRAM_CONTROLLER_0_BASE)
#define SDRAM_I ((volatile unsigned int *) NEW_SDRAM_CONTROLLER_0_BASE)

#define MEMSIZE 0x02000000

int main()
{ 
  int i, err=0;
  unsigned int i1, i2, i3;
  unsigned int ary[3];

  // SDRAMに書き込む値
  ary[0] = 0x47bd9f6a;
  ary[1] = 0x1e806c95;
  ary[2] = 0x2fdc3a5c;

  for ( int j=0; j<16; j++ ) {

	  //BYTE書き込み
	  alt_printf("%x",j);
	  alt_printf(" BYTE Checking...");

	  for ( i=0; i<MEMSIZE-3; i=i+3 ){
		  SDRAM_C[i]   = ary[0];
		  SDRAM_C[i+1] = ary[1];
		  SDRAM_C[i+2] = ary[2];
	  }

	  alt_dcache_flush_all();

	  //BYTE読み出し
	  for ( i=0; i<MEMSIZE-3; i=i+3 ){
		  i1 = SDRAM_C[i];
		  i2 = SDRAM_C[i+1];
		  i3 = SDRAM_C[i+2];
		  if( i1 != (ary[0] & 0xff ) ){
			  err=1;
			  alt_printf("\nExpected i1:");
			  alt_printf("%x",ary[0]& 0xff);
			  alt_printf(" Read Val:");
			  alt_printf("%x",i1);
			  alt_printf(" at ");
			  alt_printf("%x",i);
			  alt_printf("\n");
		  }
		  if( i2 != (ary[1] & 0xff ) ){
			  err=1;
			  alt_printf("\nExpected i2:");
			  alt_printf("%x",ary[1] & 0xff);
			  alt_printf(" Read Val:");
			  alt_printf("%x",i2);
			  alt_printf(" at ");
			  alt_printf("%x",i+1);
			  alt_printf("\n");
		  }
		  if( i3 != (ary[2] & 0xff ) ){
			  err=1;
			  alt_printf("\nExpected i3:");
			  alt_printf("%x",ary[2] & 0xff);
			  alt_printf(" Read Val:");
			  alt_printf("%x",i3);
			  alt_printf(" at ");
			  alt_printf("%x",i+2);
			  alt_printf("\n");
		  }
	  }

	  if ( err==1 )
		  alt_printf("NG!!!\n");
	  else
		  alt_printf("OK.\n");

	  err=0;

	  //SHORT書き込み
	  alt_printf("%x",j);
	  alt_printf(" SHORT Checking...");

	  for ( i=0; i<MEMSIZE/2-3; i=i+3 ){
		  SDRAM_S[i]   = ary[0];
		  SDRAM_S[i+1] = ary[1];
		  SDRAM_S[i+2] = ary[2];
	  }

	  alt_dcache_flush_all();

	  //SHORT読み出し
	  for ( i=0; i<MEMSIZE/2-3; i=i+3 ){
		  i1 = SDRAM_S[i];
		  i2 = SDRAM_S[i+1];
		  i3 = SDRAM_S[i+2];
		  if( i1 != (ary[0] & 0xffff ) ) {
			  err=1;
			  alt_printf("\nExpected i1:");
			  alt_printf("%x",ary[0] & 0xffff);
			  alt_printf(" Read Val:");
			  alt_printf("%x",i1);
			  alt_printf(" at ");
			  alt_printf("%x",i);
			  alt_printf("\n");
		  }
		  if( i2 != (ary[1] & 0xffff ) ) {
			  err=1;
			  alt_printf("\nExpected i2:");
			  alt_printf("%x",ary[1] & 0xffff);
			  alt_printf(" Read Val:");
			  alt_printf("%x",i2);
			  alt_printf(" at ");
			  alt_printf("%x",i+1);
			  alt_printf("\n");
		  }
		  if( i3 != (ary[2] & 0xffff ) ) {
			  err=1;
			  alt_printf("\nExpected i3:");
			  alt_printf("%x",ary[2] & 0xffff);
			  alt_printf(" Read Val:");
			  alt_printf("%x",i3);
			  alt_printf(" at ");
			  alt_printf("%x",i+2);
			  alt_printf("\n");
		  }
	  }

	  if ( err==1 )
		  alt_printf("NG!!!\n");
	  else
		  alt_printf("OK.\n");

	  err=0;

	  //INT書き込み
	  alt_printf("%x",j);
	  alt_printf(" INT Checking...");

	  for ( i=0; i<MEMSIZE/4-3; i=i+3 ){
		  SDRAM_I[i]   = ary[0];
		  SDRAM_I[i+1] = ary[1];
		  SDRAM_I[i+2] = ary[2];
	  }

	  alt_dcache_flush_all();

	  //INT読み出し
	  for ( i=0; i<MEMSIZE/4-3; i=i+3 ){
		  i1 = SDRAM_I[i];
		  i2 = SDRAM_I[i+1];
		  i3 = SDRAM_I[i+2];
		  if( i1 != ary[0] ) {
			  err=1;
			  alt_printf("Expected i1:");
			  alt_printf("%x",ary[0]);
			  alt_printf(" Read Val:");
			  alt_printf("%x",i1);
			  alt_printf(" at ");
			  alt_printf("%x",i);
			  alt_printf("\n");
		  }
		  if( i2 != ary[1] ) {
			  err=1;
			  alt_printf("Expected i2:");
			  alt_printf("%x",ary[1]);
			  alt_printf(" Read Val:");
			  alt_printf("%x",i2);
			  alt_printf(" at ");
			  alt_printf("%x",i+1);
			  alt_printf("\n");
		  }
		  if( i3 != ary[2] ) {
			  err=1;
			  alt_printf("Expected i3:");
			  alt_printf("%x",ary[2]);
			  alt_printf(" Read Val:");
			  alt_printf("%x",i3);
			  alt_printf(" at ");
			  alt_printf("%x",i+2);
			  alt_printf("\n");
		  }
	  }

	  if ( err==1 )
		  alt_printf("NG!!!\n");
	  else
		  alt_printf("OK.\n");
	  err=0;

	}

  return 0;
}

結果は以下の通り。

0 BYTE Checking...OK.
0 SHORT Checking...OK.
0 INT Checking...OK.
1 BYTE Checking...OK.
1 SHORT Checking...
Expected i1:9f6a Read Val:3a5c at 2a35e5

Expected i3:3a5c Read Val:5c95 at 2a35e7

Expected i1:9f6a Read Val:3a5c at 34bc15

Expected i3:3a5c Read Val:5c95 at 34bc17
NG!!!
1 INT Checking...OK.
2 BYTE Checking...OK.
2 SHORT Checking...
Expected i1:9f6a Read Val:3a5c at 159465

Expected i3:3a5c Read Val:5c95 at 159467
NG!!!
2 INT Checking...OK.
3 BYTE Checking...OK.
3 SHORT Checking...
Expected i1:9f6a Read Val:3a5c at 6c7515

Expected i3:3a5c Read Val:5c95 at 6c7517
NG!!!
3 INT Checking...OK.
4 BYTE Checking...OK.
4 SHORT Checking...
Expected i1:9f6a Read Val:3a5c at 4b5c25

Expected i3:3a5c Read Val:5c95 at 4b5c27

Expected i2:6c95 Read Val:3a5c at fffecb

Expected i3:3a5c Read Val:5c95 at fffecf
NG!!!
4 INT Checking...OK.
5 BYTE Checking...OK.
5 SHORT Checking...
Expected i1:9f6a Read Val:3a5c at 31e885

Expected i3:3a5c Read Val:5c95 at 31e887
NG!!!
5 INT Checking...OK.
6 BYTE Checking...OK.
6 SHORT Checking...OK.
6 INT Checking...OK.
7 BYTE Checking...OK.
7 SHORT Checking...
Expected i2:6c95 Read Val:3a5c at fffdab

Expected i3:3a5c Read Val:5c95 at fffdaf
NG!!!
7 INT Checking...OK.
8 BYTE Checking...OK.
8 SHORT Checking...OK.
8 INT Checking...OK.
9 BYTE Checking...OK.
9 SHORT Checking...OK.
9 INT Checking...OK.
a BYTE Checking...OK.
a SHORT Checking...
Expected i2:6c95 Read Val:3a5c at fffecb

Expected i3:3a5c Read Val:5c95 at fffecf
NG!!!
a INT Checking...OK.
b BYTE Checking...OK.
b SHORT Checking...OK.
b INT Checking...OK.
c BYTE Checking...OK.
c SHORT Checking...
Expected i1:9f6a Read Val:3a5c at 79f0f5

Expected i3:3a5c Read Val:5c95 at 79f0f7

Expected i2:6c95 Read Val:3a5c at fffdab

Expected i3:3a5c Read Val:5c95 at fffdaf
NG!!!
c INT Checking...OK.
d BYTE Checking...OK.
d SHORT Checking...
Expected i1:9f6a Read Val:3a5c at 165

Expected i3:3a5c Read Val:5c95 at 167

Expected i1:9f6a Read Val:3a5c at 249465

Expected i3:3a5c Read Val:5c95 at 249467
NG!!!
d INT Checking...OK.
e BYTE Checking...OK.
e SHORT Checking...
Expected i1:9f6a Read Val:3a5c at 37425

Expected i3:3a5c Read Val:5c95 at 37427
NG!!!
e INT Checking...OK.
f BYTE Checking...OK.
f SHORT Checking...OK.
f INT Checking...OK.

SHORTのとき異常が出ている。なんでだろ~

(2019.6.26追記)
解決した。pll出力をSYSCLKとSDRAMクロックに与えているが、SDRAMクロックの位相差を付けてなかったため、
アドレスが変化する前に書き込み、またはDQが変化する前に読みこみしていたよう。
DE0-Nanoサンプルプログラムにある通り、SDRAMクロックを-60degとした。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?