68020 とメモリのつなぎ方

Twitter で Ki さんが 68000 と PCM 音源を使った CPU ボードを設計するとのことで冗談で 68000 より小さいから 68EC020 にしろといったところ本当に EC020 を検討し始めた。ちゃんと読んでなかった 68020 のつなぎ方の記事を読んでたら自分もおもしろくなってきたという件。

ここは資料整理とメモ代わりなので、正しいデータは freescale にあるデータシートを元に設計してください。(いま設計する人は限られてるのでないと思います)

Dynamic Sizing

data bus が 32bit となったと同時に、接続するメモリの幅を 8/16/32 bit から選べる仕組み。これのおかげで奇数アドレスへの word/longword アクセスでアドレスエラーが発生しなくなった(と思う)。

以下 8bit の SRAM を data bus の幅別につなぐ方式を記載する。

8bit SRAM

//RAM
A[nn:0] = CPU_A[nn:0];
DQ[7:0] = CPU_D[31:24];
CS = CPU_A[amax:nn + 1] == xxxx && CPU_AS == 1'b0 ? 1'b0 : 1'b1;
OE = CPU_RW == 1'b1 && CPU_DS == 1'b0 ? 1'b0 : 1'b1;
WE = CPU_RW == 1'b0 && CPU_DS == 1'b0 ? 1'b0 : 1'b1;

//CPU
CPU_8BIT_DSACK[1:0] = WAIT ? 2'b11 : 2'b10;
  • A: 68020 は A1 も A0 も存在するので素直につなぐ。
  • DQ: 8bit の場合は 31 から 24。 big endian.
  • CS: 68000 と同じ. amax は 68020 は 31, 68EC020 は 23.
  • OE, WE: UDS/LDS が分離されて DS になったのでこれを含める。
  • DSACK: DTACK が DSACK[1:0] に変更。ここではウェイトが終わり次第 8bit bus cycle end である 2'b10 を CPU へ出力する。
  • SIZ と DACK の幅を表す値が異なるので注意。間違えやすい。

16bit SRAM (8x2)

size |A0|UD LD|part
                                • -
byte |0 |0 1 |1 |1 |1 0 |1 word |0 |0 0 |2 |1 |1 0 |1 + (1) 3byte|0 |0 0 |(1) + 2 + (1) [*] |1 |1 0 |1 + (2) [??] long |0 |0 0 |2 + (2) or (2) + 2 |1 |1 0 |1 + (3)
  • UD = UDS(D31:24), LD = LDS(D23:16), part = 想定される転送バイト数
  • part の 条件で()内の値は担当外の転送
  • [*] 32 bus の offset が 2'b01 でその次が 16 bit bus
  • 3byte で offset 1'b1 はないと思うんだが....
//data strobe
CPU_UDS = DS | CPU_A[0];
CPU_LDS = 
	CPU_A[0] == 1'b0 ? DS | (CPU_SIZ[1:0] == 2'b01 ? 1'b1 : 1'b0) :
	DS;

//RAM
A[nn-1:0] = CPU_A[nn:1];
U_DQ[7:0] = CPU_D[31:24];
L_DQ[7:0] = CPU_D[23:16];
CS = CPU_A[amax:nn + 1] == xxxx && CPU_AS == 1'b0 ? 1'b0 : 1'b1;
U_OE = CPU_RW == 1'b1 && CPU_UDS == 1'b0 ? 1'b0 : 1'b1;
L_OE = CPU_RW == 1'b1 && CPU_LDS == 1'b0 ? 1'b0 : 1'b1;

//CPU
CPU_16BIT_DSACK[1:0] = WAIT ? 2'b11 : 2'b01;
  • LDS: A0 == 0 のとき byte アクセスの場合には active にはならない。 A0 == 1 のときはどのサイズでも OK
  • A: 68000 同様 A1 からシフトして接続
  • DQ: 31 から 16.
  • CS: 68000 と同じ.
  • OE, WE: UDS, LDS を周辺回路で作る以外は 68000 と同じ. WE は略した。
  • DSTACK: 16bit bus cycle end は 2'b10

32bit SRAM (8x4)

size |OF|UU UM LM LL|part
                                                • -
byte |0 |0 1 1 1 |1 |1 |1 0 1 1 |1 |2 |1 1 0 1 |1 |3 |1 1 1 0 |1 word |0 |0 0 1 1 |2 |1 |1 0 0 1 |2 |2 |1 1 0 0 |2 |3 |1 1 1 0 |1 + (1) 3byte|0 |0 0 0 1 |(1) + 3 |1 |1 0 0 0 |3 ?? |2 |1 1 0 0 |2 + (1) ?? |3 |1 1 1 0 |1 + (2) ?? long |0 |0 0 0 0 |4 |1 |1 0 0 0 |3 + (1) |2 |1 1 0 0 |2 + (2) |3 |1 1 1 0 |1 + (3)
  • OF = offset, A[1:0]. 表示値としては prefix として 2'h。
  • UU = UUDS, D31:24
  • UM = UMDS, D23:16
  • LM = LMDS, D15:8
  • LL = LLDS, D7:0
  • 3byte がいまいち理解できず。
//data strobe
CPU_UUDS = DS | (CPU_A[1:0] == 2'00 ? 1'b0 : 1'b1); //D31:24
CPU_UMDS = DS == 1'b1 ? 1'b1 : umds(CPU_A, CPU_SIZ);
CPU_LMDS = DS == 1'b1 ? 1'b1 : lmds(CPU_A, CPU_SIZ);
CPU_LLDS = DS == 1'b1 ? 1'b1 : llds(CPU_A, CPU_SIZ);

function umds;
	input [1:0] cpu_a;
	input [1:0] size;
	case(cpu_a)
	2'h0: umds = (size == 2'b01 ? 1'b0 : 1'b1);
	2'h1: umds = 1'b0;
	2'h2, 2'h3: umds = 1'b1;
	endcase
endfunction

function lmds;
	input [1:0] cpu_a;
	input [1:0] size;
	case(cpu_a)
	2'h0:
		case(size)
		2'b01, 2'b10: lmds = 1'b1;
		2'b11, 2'b00: lmds = 1'b0;
		endcase
	2'h1: 
		case(size)
		2'b01: lmds = 1'b1;
		2'b10, 2'b11, 2'b00: 1'b0;
		endcase
	2'h2: lmds = 1'b0;
	2'h3: lmds = 1'b1;
	endcase
endfunction

function llds;
	(略)
endfunction

//RAM
A[nn-2:0] = CPU_A[nn:2];
UU_DQ[7:0] = CPU_D[31:24];
UM_DQ[7:0] = CPU_D[23:16];
LM_DQ[7:0] = CPU_D[15:8];
LL_DQ[7:0] = CPU_D[7:0];
CS = CPU_A[amax:nn + 1] == xxxx && CPU_AS == 1'b0 ? 1'b0 : 1'b1;
UU_OE = CPU_RW == 1'b1 && CPU_UUDS == 1'b0 ? 1'b0 : 1'b1;
UM_OE = CPU_RW == 1'b1 && CPU_UMDS == 1'b0 ? 1'b0 : 1'b1;
LM_OE = CPU_RW == 1'b1 && CPU_LMDS == 1'b0 ? 1'b0 : 1'b1;
LL_OE = CPU_RW == 1'b1 && CPU_LLDS == 1'b0 ? 1'b0 : 1'b1;

//CPU
CPU_32BIT_DSACK[1:0] = WAIT ? 2'b11 : 2'b00;
  • UUDS, UMDS, LMDS, LLDS はここまでくると面倒なので表をそのまま読めるように function で case を組みまくった方がよいと思われる
  • A: A2 からシフトして接続
  • DQ: 31 から 0 の全てを使う.
  • CS: 68000 と同じ
  • OE, WE: WE は略。 CPU_WR == 1'b0 && (OEとおなじ)
  • DSTACK: 32bit bus cycle end は 2'b00

総評

32bitの data strobe を作るのが大変で、奇数アドレスへの word/long のアクセスはアドレスエラーをだしてもいいのではと思った。アドレスエラーでなくもののバスエラーならだせるので、 A[0] == 1'b1 のときに SIZ が word/long のときは発生。そうすれば SIZE == 3byte も発生しない気がする。