alu181
// iCEDIP24 modified 74181 iCEDIP24
// 37 B0 1 24 VCC
// 43 A0 2 23 A1 36
// 44 S3 3 22 B1 35
// 45 S2 4 21 A2 34
// 46 S1 5 20 B2 32
// 47 S0 6 19 A3 31
// 48 Cn 7 18 B3 26
// 2 M 8 x 17 N.C. 25 (/P)
// 3 F0 9 16 Cn+4 21
// 4 F1 10 x 15 N.C. 20 (/G)
// 9 F2 11 14 EQ 19
// GND 12 13 F3 18
大昔の 4bit Arithmetic Logic Unit(ALU) 74181 である。本物は今や超高価で取引されている。せっかく 24 pin にしたのだから互換品を作ってみよう。ただし /P と /G は、carry-lookahead generator 74182 と共に使用するもので、パス。
ALU は、FF を持たないただの組み合わせ回路で非同期に動作する。
参考:ALUに使うTTLの決定
1) alu181,v を デザインファイルに入れて、論理合成 -- 問題ない。
2) pin Constants Editor で ピンアサインを変更。
不思議なことに、制限がある信号が出てきた。とりあえず割り当てられたものをロックして、再度やりなおすと 制限がなくなっている。さらに不思議であるが、とりあえずロックして pcf ファイルを作成。(alu181.pcf: 以降使用可能)
// iCEDIP24 modified 74281 iCEDIP24
// 37 A1 1 24 VCC
// 43 A2 2 23 A0 36
// 44 RS1 3 22 CP 35
// 45 RS0 4 21 SIO0 34
// 46 RC 5 20 AS0 32
// 47 SIO3 6 19 AS1 31
// 48 A3 7 18 AS2 26
// 2 Cn 8 17 M 25
// 3 N.C. 9 x(/G) 16 F0 21
// 4 Cn+4 10 15 F1 20
// 9 N.C. 11 x(/P) 14 F2 19
// GND 12 13 F3 18
74281 は ALU にレジスタが付いたアキュームレータで、74181 より もっとレア。... というか現物がない!
データーシート:
AM25LS281XC
DM74S281N
こちらは、同期回路でありクロックがある。さて、どうなる?
1) acc281,v を デザインファイルに入れて、論理合成 -- 問題ない。
2) pin Constants Editor で ピンアサインを変更。
こちらも何か変? だが、ピンアサインは成功した。(acc281.pcf)
ワーストで 79.5 MHz で動作すると出た。
sram128
// iCEDIP24 2K RAM/ROM iCEDIP24
// 37 A7 1 24 VCC
// 43 A6 2 23 A8 36
// 44 A5 3 22 A9 35
// 45 A4 4 21 /WE 34
// 46 A3 5 20 /OE 32
// 47 A2 6 19 A10 31
// 48 A1 7 18 /CE 26
// 2 A0 8 17 D7 25
// 3 D0 9 16 D6 21
// 4 D1 10 15 D5 20
// 9 D2 11 14 D4 19
// GND 12 13 D3 18
かつて 24pin の SRAM や PROM があった。8bit 幅で 2KB である。これを再現する。が、MachXO2-256 は EBR がないので、128B までしか生成できなかった。
とりあえず、128B のものがどうなるか?
1) sram128,v を デザインファイルに入れて、論理合成 (RAM_USE_CLK を指定)。
2) 2KB SRAM 用 ピンアサイン sram2k.pcf を使用。
Device Utilization Summary
LogicCells : 3/5280
PLBs : 3/660
BRAMs : 1/30
IOs and GBIOs : 18/36
RAM は、非同期である。が、それでは FPGA では具合が悪い。同期SRAM というものもかつてあったが、簡易的に CE ↓ で動作するように変更した。(RAM_USE_CLK)。これだと全然問題なく、EBR を使用する。
で、RAM_USE_CLK を undefine すると、WE ↓ で書き込みをするが、非同期にデータを出力する。
Device Utilization Summary
LogicCells : 2181/5280
PLBs : 329/660
BRAMs : 0/30
IOs and GBIOs : 18/36
なんだかものすごいことに。128 x8 だから 1024 個の D-FF で作れるのだが、実際に 1024 個の LUT を D-FF として使用している。
MachXO2 は 256 なのに、この 1024 bit が入る。これは LUT に機能追加して 4bit レジスタに出来るからである。こういう工夫をしてもザイリンクスの方がさらに少ない LUT 数で実装できる。iCE40 は、単純な LUT 構造なのかも知れない -- 要調査である。
さて、他にオプションがある。RAM_INCLUDE_DAT - 初期値つきである。うまく出来ないと今後困る。また、書き換え不可にして、rom 化も試さなければ。rom 化では、普通は構造が変わる。組み合わせ回路になり、LUT あたり 16bit 分実装する。EBR を使うようにするには、何か指定がいる。
rom は、論理的には case 文で書くようなロジック。case 文の中身を 別ファイルにして `include するという方法はある。
最初の問題は、データファイルの読み込ませ方。ググると 「iCEcube2 User Guide」に書いてあるとのこと。$readmemh を使えば良いらしいが、うまくいくのかどうか?
- 実は思うように行ってない。後回し。
sram2k
まずは単純に サイズを大きくしてみる。
Device Utilization Summary
LogicCells : 3/5280
PLBs : 3/660
BRAMs : 4/30
IOs and GBIOs : 22/36
クロックに関する情報を期待したのだが、見つからない。
さて、$readmemh だが、
Cannot find data file rom_data.mem for task $readmemh
要するに、どこにファイルを置くのかという問題。面倒なことに warning であって ファイルがないと初期値が入らないだけ。Synplify Pro だと write 禁止にすることで、0 を出力するだけの回路になって アドレスが削除された結果になる。
ファイルを プロジクトディレクトリの上階層に置いて、ファイル名を "../rom_data.mem" とすることで、上手くいった。EBR を 4 つ使った 2KB の ROM も OK 。ただし、繰り返しデータのパターンだと EBR が1つになったりする。
他にツールで 初期値を設定する方法もあるらしい。物理的な EBR を指定しないといけないが、データだけを変更して使うような用途では、良いかも知れない。
つでに SPRAM もやってみた。SPRAM は、16K x 16bit のファンクションブロックが4つ。初期化できるかどうかは分からない。
clock1
// iCEDIP24 iCEDIP24
// 37 1 38 24 VCC
// 43 2 23 36
// 44 3 42 22 35
// 45 DIG1 4 21 E 34
// 46 A 5 20 D 32
// 47 F 6 19 DP 31
// 48 DIG2 7 18 C 26
// 2 DIG3 8 17 G 25
// 3 B 9 16 DIG4 21
// 4 10 15 BTN_UP 20
// 9 11 14 BTN_DN 19
// GND 12 13 BTN_SEL 18
ボタン操作がある時計である。表示は 7セグメントx4 ダイナミック点灯。論理合成できるかどうか?というのが最初のポイント。
ピンアサインは、4桁の7セグに合わせてみた。4桁の7セグは大きさが2種類ある。ピンアサインは同じだが幅が、400 mil と 600mil 。400 mil の裏側に付けるイメージで割り当て。
1) 4つのファイル clock1,v button.v seg7dec.v time_counter.v を使用
2) clock1.pcf を指定
No support for synthesis of mixed edge and level triggers. (Lattice LSE)
Can't mix posedge/negedge use with plain signal references (Synplify Pro)
→ always @(R, negedge CLK_128HZ)
ダメですな。どういうつもりで作ったか思い出さないと、先に進めない。当時 posedge/negedge を気にしないで作ってたような ... これがダメなら、どう対応するのが良いかちゃんと調べないとまずい。
クロック関係のメモ:
8MHz などのクロックを negedge で動かし分周し、128Hz や 1Hz を生成して、新たなクロックソースにしている。 CLK_128HZ は、posedge と negedge を混ぜて使っているようだ。
上記の問題だが R はリセットのつもりなのだが、外してしまっても良さそうなので、外すと OK だった。混乱した理由は、ファイルのセーブをちゃんとしてから論理合成しないといけないという点。ファイルの編集はただのエディタであった。なお、posedge と negedge を混ぜることは問題ないようだ。
ボタン:
チャタリング対策をしてある。シフトレジスタに 128Hz でボタンの HL を記録していって、0000 または 1111 で状態遷移。このためにクロックが必要なのであった。
ボタンは、プルアップにして −スイッチーGND と接続する。pcf ファイルは、
set_io BTN_UP 20 -pullup yes
こんな風に記述する。
XIN と XOUT :
時計なのだから、水晶発振器を XIN につなぐのが、ひとつの方法。XOUT は XIN の反転出力。うまくすれば、水晶発振子をドライブできるはずである。その際に入力のディレイとか設定がいるかも知れない。
また実験では、内蔵オシレータを使ってみようかと思う。10kHZ で十分だが、HFOSC にプレスケーラがあるので 48MHz/8 = 6MHz を使ってみる。
Device Utilization Summary after Packing
LogicCells : 235/5280
PLBs : 38/660
BRAMs : 0/30
IOs and GBIOs : 17/36
LFOSCs : 0/1
HFOSCs : 1/1
うまくいった。
ドライブ能力の問題:
1つのピンの能力は 3.3V 8mA である。これだと、DIGx ピンの制限がネックになるため LED 1つへの電流が 1mA になるようにしないといけない。それでダイナミック点灯させるのは厳しいので、ドライブ用に トランジスタを付けたい ... となるとカソードコモンを使用して DIGx の論理を逆転させる必要がある。結局点灯させたいときは、両方 H にする。アノードコモンならば、逆。両方 L で点灯。PCH MOSFET を使う。
時計用 4桁 7セグ:
aliexpress で探すと、中央に 2dot がある 時計用 のものがある。5 個セットとかになってしまうが、安価に入手できる。ピンアサインは 12ピンのものは互換性があるようだ。小数点もあるものは、2桁め 小数点も含めて 3 dot 同時点灯になる模様。(”7 Segment Clock Digit” で検索)
dac
DSD64 は、44.1kHzの64倍=2.8224MHz での 2値データらしい。ΣΔ DAC なら PCM データを 64 倍にオーバーサンプリングして、ΣΔ変調すれば、良さそうである。この程度であれば、周波数的に難しいことではない。コンポジット出力などでは、14.318MHz で データを出力しなければならない。28MHz 8bit ぐらいの性能が必要。FPGA が 4倍の 112 MHz で動くかどうかすら怪しく、多値出力をしないといけないのだが、R2R ラダーは精度を取るのが難しいらしい。3bit あるいは 4bit で R2R を作って、ディザでごまかす程度ならなんとかなるかも知れない。
液晶を使う場合、SPI 液晶が扱いやすい。しかし、SPI では書き換え速度を速くできない。パラレルを使えば良いのだが、信号線が増えて面倒。CR で扱えるのであれば コンポジット出力も悪くないとは思う。
さて、こういうことを考えて、ΣΔ DAC を作ってみよう。... というのを過去にやった。今はソースだけ残っていて、思い出すところから始めないと。
dac_sd.v
とりあえず論理合成はできる。16bit を外部から入力して Frequency: 73.81 MHz だそうだ。しかし MODE とか何のつもりだったのか?
dac_sd3.v
こちらは、8bit を外部から入力して 3bit 出力。 Frequency: 116.16 MHz だそうだ。
14MHz の 8倍 クロックが使えるかも。
中身は思い出せない。今回はクロックの見積もりだけ。
アンプについて:
R2R ラダーは、抵抗の精度が必要な上に、FPGA の出力ポートの抵抗値も考慮する必要がある。そうすると、1KΩ以上の抵抗を使用したい。となると今度はアンプが必要になる。OP アンプを ボルテージフォロワで使えば良いのではないかと思うのだが、それなりに帯域が必要。小さいものを探すと SOT23-5 のものがある。aliexpress だと 110MHz の AD8091ARTZ が見つかった。安価に入手できなくなる可能性があるので、mouser でピン互換のものを探すと MCP6L91 が安かった --- ただし帯域は 10MHz。NJM2741F も安いがピン互換ではなかった。他に TSV991 (20MHz) など。
この回路そのもの。アンプに抵抗などいらないので、配線は簡単である。R は、誤差 1% のもので 1.5K, 3K を使おうかと思っている。
サウンドの場合は、もっと安いオペアンプが使える。aliexpress では、LM321 や MCP6001T が安価。ただし、ピンアサインが違う。(MCP6001T として売ってるのは AFxx というマークであり MCP6001U の模様)
イヤホンや小型スピーカーを鳴らしたいのであれば、aliexpress で CKE8002B がとにかく安い。
メモ:
・https://opencores.org/project,sigma_delta_dac_dual_loop
ΣΔ DAC について VHDL で作成されているが、まともそうな作例があった。
オーバーサンプリングについて甘くみてたかも。
考え方として、データの間に 0 を挿入したものを処理前データとする。64 倍なら、1 つのデータと 63 個の 0 。それを LPF にかけると ... 補間されたデータが出てくる。LPF には FIR フィルタというものを使うが、タップ数が非常に多くなる。64 タップでも 1つしか実データがないのだから当然だ。FIR フィルタは、タップ数分の 積和演算が必要で オーバーサンプリングの度に行わなければならない。
まっとうにやるとすごい量だが、63 個は 0 なので計算する必要がない。結局のところ タップ数 / 64 の計算で済む。... だが、タップ数がべらぼうに多くなる。128 タップ程度では 2 つの実データを含むだけである。32 個分で 2048 とか?
実をいうと ここ 見て自分の理解を書いているだけなのだが、4 倍オーバーサンプリングで 128 タップ = 32個の実データとなっている。周波数特性がどうのという話だろうから、64倍だろうと、32個の実データで良いのだろうと想像した。
44.1 kHz の 64倍 で 32 回の 積和演算を 1つの乗算器で行うならば、90 MHz で毎回計算しないといけない。DSP 16x16 は 最大 50 MHz だから無理ですな。
しかし別のヒントがあるかも知れない。「ポリフェーズフィルタの基本を知る」 これを理解しなければならないようだ。
あるいは、3bit R-2R DAC 出力 にして、16 倍オーバーサンプリングにまで落とすとか。これなら実現可能である。
オーディオは上記のような話だが、コンポジット信号はどうなのだろうか?
「14.314MHzでV、U、−V、−Uを順番に出力する」ということなので、サンプリングデータ間に関係がないのである。波形全体に LPF をかけるのはダメのような。さらに 8 倍クロックで動かすとして 8 クロックで V なら V を出力し、前後のことは知らないということで良さそうな気がする。それならば波形データを持っていても良い。3bit DAC + ディザなら 5clock 分で 15bit だ。5 倍クロックにしよう。元の色空間が 12bit だけとすれば、4096 x 16bit = 8KB で済む。VとUが独立ならば、例えば 16 x 16bit + 256 x 16bit とか。
もはやΣΔは関係ない世界なのであった。
ついでなので書いておくと、Nanopi DUO などは、最終段に 50Ωと LC LPF が入っている。
他にもいろいろ設計したのがあるが、とりあえずここまで。
・icedip-samples-01.zip
さて、ネタが溜まってくると基板を設計したくなる。
まずコンポジット信号のお勉強から。
信号レベル 1Vpp (-40 IRE 〜 100 IRE)
水平同期 -40 IRE 〜 0 IRE
カラーバースト -20 IRE 〜 20 IRE
信号レベル 0 IRE 〜 100 IRE
どうも 1Vpp を -40 IRE 〜 100 IRE になるよう単位を決めているようだ。バースト信号などを切りの良い値にするため 4bit の R-2R DAC にして、0 - 14 を使うのが良さそう。そのうち 4 - 11 の 8レベル をY信号に割り当てる。
カラーサブキャリア周波数: 3579545Hz これを 1T とする。
水平期間 227.5T
水平ブランキング 39T
0IRE 6T
水平同期パルス(-40IRE) 17T
0IRE 2T
カラーバースト(10 -20 20 ... 20 -10 RE) 9T
0IRE 5T
残:188.5T
画像範囲 140T (apple2) , 128 ? (SFC) 2dit/T ?
間違ってるかも知れないが、おおむねこんな感じ。あと、全く同じタイミングで画像を出力すると、1ライン毎に 0.5T ずれて表示される(らしい)。
ノンインターレースでは、1フレーム 262H で 20H の垂直ブランキングから開始。画像は 242H まで。
画像範囲 192H (apple2) , 224H or 239H (SFC)
めんどくさくなったので、とりあえずここまで。まず知りたいのは、信号レベルの話。
Y信号は、4 - 11 の 8レベル を割り当て、2dot/1T で表示する。
色差信号は、V、Uを 1T 毎に生成して、V、U、−V、−Uを順番に Y信号に加算?
- 絶対値を 5 レベルまでにしないと オーバーフローが起きる。
- 負の値もあるので、 9 レベル
さて、R-2R のレベルは? ボルテージフォロワなら、0 - 3.3 x 15/16 = 3.094
出力を 1/3 にしないといけないから、アンプの出力に 100Ω を入れて 50Ω の 抵抗でプルダウン。
普通のオペアンプの使い方だと、RI = 30kΩ , RF = 10kΩ とかで ゲインを 1/3 にして 出力の 100Ωは入れない。また反転だから、値の扱いを逆にする。
どっちが良いのだろうか?
次、ディザ。端数だけ 0/1 で表現するなら 5 clock で 5 レベルしか表現できない。Y は 8x5 = 40 階調、U,V は 45 階調ということに。
だいぶ半端な感じである。フレームバッファは 8bpp にしてパレットを使うというのが良いかも知れない。
参考)
・ビデオ信号計測・生成の基本
・RS-170A NTSCビデオ信号タイミング規格の概要
だいぶ作れそうな気がしてきた。次のお題はクロック。14.314 MHz の水晶を 元として 内蔵 PLL を 使い 5倍にして、71.57 MHz をメインクロックにすれば良いのだろうか? そうしたときサウンドはどうするのだろう?
71.57 MHz / 44.1 kHz = 1622.9 だから 1623 が割と近い。だが、3 x 541 にしか素因数分解できないく、扱いにくい。1622 にしても 2 x 811。1624 なら、7 x 8 x 29 うーん。
1625 まで行くと 5 x 13 x 65 。
だいぶずれるが 1620 なら 4 x 5 x 9 x 9 。そのかわりサンプリング周波数が 44.179 にまでなってしまう。0.18 % の誤差。こんなので作れるのだろうか? 予定と随分と違う −不安になって来た。
あるいは、48kHz 系。8kHz や 16,24kHz サンプリング周波数に対応できる。
71.57 / 1488 = 48.098 (0.2% の誤差) , 1488 = 16 x 3 x 31
別に高性能なものを作りたいわけではないので、こちらの方が良いかも。
参考)
・素数判定ツール
追記)すごく参考になりそうな所を見つけた
・FPGA1ピンでNTSC出力をする方法
・FPGA 1pinで NTSCを出力する方法 ソース付き (最終)
・48fsc(171.8MHz)で動作させる。
・ΔΣADPCM(1bit)
なるほど、計画したのは、20fsc(71.57MHz) だから倍ほどのクロック。FIR フィルタを使わなければ、実現できるのかも知れない。ソース付きか、勉強させてもらおう。
他に、「NTSCベースの44.056 kH」? 14.314 MHz の 1/325 ということ?
・FPGA活用回路&サンプル記述集(3) ―― ビデオ信号処理回路
これもチェックしておこう。
他にこういう説明を発見
「NTSC は 858x525 の信号(ITU-R BT601 の場合)で構成され、このうち帰線消去期間(垂直・水平同期信号、カラーバースト信号、文字放送信号、放送局制御信号)などを除いた画像表示領域が 720x480 の大きさである。 しかし、実際の TV では 720x480 の情報を全て表示できるものは少なく、大抵は 686x456 程度 ...」
メモ:
14.314 MHz のクロックを基準にすると、1 ラインは、910 クロックである。水平ブランキングに 39*4 クロック必要なので、754 クロック。 このうち 686/858 が表示できるということは、727.5 クロック。余白が左右 13 クロック必要と。2 クロックで 1 dot 表示することにするならば、363 dot ぐらいが限界。また、ライン数はノンインターレースで 228 程度。全部で 262.5 ラインあるが、垂直同期に 9 or 10 ライン使用し、さらに文字放送などで 12 ライン分つかう。262 - 21 = 241 あるが 228 ということは、上下 13 ラインは表示しないほうが良さそうということか。
その他、簡単なものだと、ADC とかも可能。
・https://github.com/mcmayer/iCE40/tree/master/adc
Lattice 社がリファレンスデザインを出している。差動入力があれば FPGA を選ばないようだ。
リファレンスデザインは、PWM で電圧を出力して 入力と比較するやり方。
・https://github.com/mcmayer/iCE40/tree/master/adc
UP5K は SPRAM がある。フレームバッファとか表示系が簡単に作れそう。未だにコンポジット入力の液晶モニタが安価で買える。4.3 inch なら $12 程度で 解像度はたぶん 480 x 272 。 16bpp だと無理だが、8bpp ならなんとか。
・ http://fpgapark.com/ntsc/ntsc.htm
こういうのを作っている人もいるし出力は作れそう。
・ http://bitluni.net/esp32-composite-video/
ただ ESP32 で結構なことが出来るのである。DAC でコンポジット出力が可能! 白黒のみみたいだが。
車のバックモニタ用として、まだ現役で安価に買える。写真のものは 4.3 インチで $11.84 。電源は 12V 、2系統の入力がある。いずれはなくなって行くのだろう。よく知らないが、代わりにデジタルのものが出てくるのだろう。そうなれば ... かえって簡単になるのかも知れないが。
・このショップが安いようだ。4.3 inch $12 , 5.0 inch $16 ぐらい。
その他メモ
・https://github.com/grahamedgecombe/icicle
Icicle is a 32-bit RISC-V system on chip for iCE40 HX8K and iCE40 UP5K FPGAs.
https://github.com/aventuri/iceProgrammer
i used direct memory map access for GPIO I/O, suitable for A10 A20 Allwinner
https://github.com/nesl/ice40_examples