Compact Flash(以下CF)もobsolute化進行中のストレージだがSDcardコントローラを書く(ハード/ソフト含めて)能力も無く伝統のTrue IDE modeを想定する。
1.基本タイミング
ネットで拾ったCFのデータシート(確か日立製作所)からTrue IDEのタイミングを以下に引用する。
・True IDE mode read timing
・True IDE mode write timing
あまりの遅さに若い方は失神されるかもしれないが20世紀のデバイスはこんなもんだったんです。なのでそれに合わせる為に(主にtsuA(IORD/IOWR),tw(IORD/IOWR)を満たす為のタイミング生成(とdsack生成)がステートマシンのお仕事になる。
2.ステートダイヤグラム
今回はiverilog-gtkwaveで試行錯誤した構成から逆生成したので正確さはあるが緊張感に欠けるかもしれない。
・graphvizのコード( .dot )
// 2021/11/27 : verilogコードとgtkwaveから逆生成
// 2021/11/23 : CF用iosqを再整理、特にdsack
// ステートの割当て
//S0(000) : a == CF && as_b == 0 , wcnt <= w1
//S1(001) : wait w1 , wcnt <= w2
//S2(011) : wait w2
//S3(111) : wait ~cpuclk , wcnt <= w3
//S4(110) : wait w3
//S5(100) : wait as_b
digraph {
//rankdir=LR;
graph [ layout = dot ];
node [shape = doublecircle]; S0 S1 S2 S3 S4 S5 ;
node [shape = parallelogram]; CF_iocycシーケンス;
node [shape = ellipse]; iosq;
node [shape = rarrow]; cf_ce_n cf_iord_n cf_iowr_n dsack_n;
CF_iocycシーケンス -> S0 [ label = "CF iocyc制御" ];
S0 -> S1 [ label = "a == CF && as_b == 0 , wcnt <= w1" ];
S1 -> S2 [ label = "wait w1 , wcnt <= w2"];
S2 -> S3 [ label = "wait w2" ];
S3 -> S4 [ label = "wait ~cpuclk , wcnt <= w3" ];
S4 -> S5 [ label = "wait w3"];
S5 -> S0 [ label = "wait as_b == 1" ];
S1 -> cf_ce_n [ label = "Assert cf_ce_n" ];
S5 -> cf_ce_n [ label = "Negate cf_ce_n" ];
S2 -> cf_iord_n [ label = "cpurw=read,Assert cf_iord_n" ];
S5 -> cf_iord_n [ label = "Negate cf_iord_n" ];
S2 -> cf_iowr_n [ label = "cpurw=write,Assert cf_iowr_n" ];
S4 -> cf_iowr_n [ label = "Negate cf_iowr_n" ];
S3 -> dsack_n [ label = "Assert dsack_n"];
S5 -> dsack_n [ label = "Negate dsack_n"];
S0 -> S0 [ label = "wait iocyc start"];
S1 -> S1 [ label = "wait w1 sysclk"];
S2 -> S2 [ label = "wait w2 sysclk"];
S3 -> S3 [ label = "wait cpuclk=0"];
S4 -> S4 [ label = "wait w3 sysclk"];
S5 -> S5 [ label = "wait as_b"];
S0 -> iosq ;
S5 -> iosq ;
}
graphvizマジック?で3bit johnsonカウンタのステートダイヤグラムが何かごちゃごちゃやってる様に見える不思議。graphvizは読む側は知れぬが書く側には優しい。
今回はw1,w2,w3なる待ち時間を生成してそれを元に各タイミングを生成するのがお仕事になる。
3.コードに落とす為の設計メモ
タイミングチャートからステートダイヤグラムを設計しCPLDのコードに落とす前に各ステートの細目とベースカウンタ(例によってジョンソンカウンタ)から生成する各タイミングを整理しておく。
// 2021/11/23 : CF用iosqを再整理、特にdsack
S0(000) : a == CF && as_b == 0 , wcnt <= w1
S1(001) : wait w1 , wcnt <= w2
S2(011) : wait w2
S3(111) : wait ~cpuclk , wcnt <= w3
S4(110) : wait w3
S5(100) : wait as_b
L0 : S0 S3
L1 : S1 S4
L2 : S2 S5
w1 : □---□
w2 : □----□
w3 : □-----□
ce : ○---------------------------------○
rd : ○----------------------------○
wr : ○--------------------○
ak : ○-------------○
ce = L0 | L2
rd = L1 | L2
wr = L1
ak = !L0 & L2
我流メモで意味不明な点はご容赦。
4.1 verilogコード(抜粋)
// CF bus cycle sequence
always @( cpuclk or iosq or a or as_b ) begin
case ( iosq )
S0 : if ( as_b == 0 && a == cf ) begin
nwcnt <= 0 ; //4'd4 ;
niosq <= S1 ;
end
else
niosq <= S0 ;
S1 : if ( wcnt != w1 ) begin
nwcnt <= wcnt + 1 ;
niosq <= S1 ;
end
else begin
nwcnt <= 0 ;
niosq <= S2 ;
end
S2 : if ( wcnt != w2 ) begin
nwcnt <= wcnt + 1 ;
niosq <= S2 ;
end
else
niosq <= S3 ;
S3 : if ( ~cpuclk )
niosq <= S3 ;
else begin
niosq <= S4 ;
nwcnt <= 0 ;
end
S4 : if ( wcnt != w3 ) begin
nwcnt <= wcnt + 1 ;
niosq <= S4 ;
end
else
niosq <= S5 ;
S5 : if ( as_b )
niosq <= S0 ;
else
niosq <= S5 ;
endcase
end
assign cf_ce_n = ~( ( iosq[0] | iosq[2] ) & ~as_b ) ;
assign cf_iord_n = ~( ( iosq[1] | iosq[2] ) & ~as_b & cpurw ) ;
assign cf_iowr_n = ~( iosq[1] & ~as_b & ~cpurw) ;
assign dsack_n = ~((~iosq[0] & iosq[2]) ) ;
4.2 テストベンチ(抜粋)
task cf_cyc ;
input [7:0] adr ;
input rw ;
begin
#(STEP);
a = adr ;
cpurw = rw ;
#(STEP);
as_b = 0 ;
if(cpurw)
ds_b = 0 ;
#(STEP);
if(~cpurw)
ds_b = 0 ;
// wait(~dsack_n);
#(STEP*2*7);
as_b = 1 ; ds_b = 1 ;
#(STEP);
cpurw = 1 ;
#(STEP*3);
end
endtask
4.3 シミュレーション結果(iverilog + gtkwave)
・印刷形式
遅まきながら`timescale 1ns / 100psに設定したのでまともな時間軸になってる筈。
5.合成結果(或いは今回のオチ)
cpldfit: version P.20131013 Xilinx Inc.
Fitter Report
Design Name: dramc Date: 11-24-2021, 11:30PM
Device Used: XC95108-20-PC84
Fitting Status: Successful
************************* Mapped Resource Summary **************************
Macrocells Product Terms Function Block Registers Pins
Used/Tot Used/Tot Inps Used/Tot Used/Tot Used/Tot
71 /108 ( 66%) 154 /540 ( 29%) 115/216 ( 53%) 33 /108 ( 31%) 46 /69 ( 67%)
いつの間にやらマクロセル使用率が66%に増加している。前回の構成から25MC増加してるのは流石におかしいと色々調べてみたが原因判明せず。ベースカウンタを4ビットジョンソンにしてwcntカウンタを除去(FF数は減ってる筈)したら逆に75MCになってしまいこれがタイトルの所以である。もっとも今時の湯水の如くマクロセルなりロジックブロックを使えるデバイスからしたら108MCなぞ無いのと同じであろうが5V系のobsoluteなCPLD(且つIMTの世界)では今後の回路ブロック更新は慎重にならざるを得ない。。。