Posts Issued in January, 2024

posted by sakurai on January 18, 2024 #736

サウンドミキサーの検証

bsvでモジュールを開発するに際して、正解値を出力するverilogモジュールを作成しました。それぞれのモジュールを駆動するテストベンチはbsvのステートマシン合成で簡単に作成できます。verilogの世界で統合するために、テストベンチの上位にverilogの最上位階層を設けます。なぜならbsvの最上位であるテストベンチ階層にはクロックもリセットも存在しないため、verilogの最上位階層を設けてクロックとリセットをテストベンチに供給してやる必要があるためです。

ここまでは通常のBSV⇒verilogシミュレーション手法ですが、最上位階層を統合して一つにすれば、その中に2つのbsvから生成されたverilogのステートマシンとそれに接続されるverilogモジュールが配置されることになります。

表736.1 verilogとbsvの階層構造
Verilog
ファイル名 自モジュール名 子モジュール名
topVeri.v mkTop mkTbVeri
mkTbVeri.v
(自モジュール名と一致させる)
mkTbVeri mixer
mixer.v
(自モジュール名と一致させる)
mixer -
BSV⇒Verilog
bsvファイル名 生成verilog
ファイル名
自モジュール名 子モジュール名
--- top.v mkTop mkTb
TbMixer.bsv mkTb.v
(自モジュール名と一致するファイル名が生成)
mkTb mkMixer
Mixer.bsv mkMixer.v
(自モジュール名と一致するファイル名が生成)
mkMixer -

top階層からverilogモードによるC-c C-aで自動結合するには、自モジュール名とファイル名が一致する必要があります。

ここで最上位階層top.vを統合して一つにし、テストベンチを2つ配置します。これで正解値と比較してデバッグし以下のミキサーが完成しました。以下にコードを示します。

typedef Int#(8) Esound_t;
typedef Int#(16) Lsound_t;

interface Mixer_ifc;
   (* prefix="" *)
   method Lsound_t mout(
      Esound_t ch0,
      Esound_t ch1,
      Esound_t ch2,
      Esound_t ch3
      ); // output
   (* prefix="" *)
   method Bool soundon(
      Bool son0,
      Bool son1,
      Bool son2,
      Bool son3
      ); // output
endinterface

(* synthesize, always_enabled = "mout, soundon", no_default_clock, no_default_reset *)
module mkMixer(Mixer_ifc);
   function Bit#(9) repeatBit(Bit#(1) b);
      Bit#(9) result = 0;
        for (Integer i = 0; i < 9; i = i + 1) begin
           result = result << 1;
           result[0] = b;
        end
      return result;
   endfunction

   method Lsound_t mout(
      Esound_t ch0,
      Esound_t ch1,
      Esound_t ch2,
      Esound_t ch3
      ); // output
      let tmp0 = pack(ch0);
      let tmp1 = pack(ch1);
      let tmp2 = pack(ch2);
      let tmp3 = pack(ch3);
      Int#(16) itmp0 = unpack({repeatBit(~tmp0[7]),tmp0[6:0]});
      Int#(16) itmp1 = unpack({repeatBit(~tmp1[7]),tmp1[6:0]});
      Int#(16) itmp2 = unpack({repeatBit(~tmp2[7]),tmp2[6:0]});
      Int#(16) itmp3 = unpack({repeatBit(~tmp3[7]),tmp3[6:0]});
      Int#(16) tmp4 = itmp0 + itmp1 + itmp2 + itmp3;
      let tmp5 = tmp4 << 6;
      return tmp5;
   endmethod
  method Bool soundon(
      Bool son0,
      Bool son1,
      Bool son2,
      Bool son3
      ); // output
      let sdon = son0 || son1 || son2 || son3;
      return sdon;
   endmethod
endmodule   

まずげた履き符号から2の補数表現に変換するために、MSBの反転を行います。次にそれを符号拡張し16ビット整数とします。それらを加え合わせてスケーリングを行います。

シミュレーションの結果、4つのチャネルにどんな値が入力されてもオーバーフローやアンダーフローが起きないことを検証しています。


左矢前のブログ 次のブログ右矢

posted by sakurai on January 17, 2024 #735

サウンドミキサーの仕様

8bit符号無し$\dagger$のwave形式のサウンドを4多重して16bit符号付きに変換するサウンドミキサーを作成します。

  • 入力: 4チャンネルch0~3のwave(PCM, 11.025KHz、8bit、Mono、メタデータ無し)
  • 出力: 1チャンネルwave(PCM, 11.025KHz、16bit、Mono、メタデータ無し)

まず8bit符号無し数を加算操作を行うために8bitの2の補数表現に変換します。それにはゲタ8'h80を引き算する必要があります。しかしながら、引き算はコストが高いため、MSBの反転を行います。以下にそれで良いことをChatGPTに証明してもらいました。

8bitゲタ履き数を8bitの2の補数表現に変換するにはゲタを引き算するのが常道ですが、MSBの反転でも良いことを数学的に証明してください。

ChatGPT:

8ビットの「ゲタ履き数」(8'h80がゼロとされる特殊な表現)を8ビットの2の補数表現に変換する際に、MSBのみを反転する方法が等価であることを証明します。

特殊な表現

この表現では、8'h80がゼロとされます。したがって、この表現における任意の値 $V$は、標準的な2の補数表現における値 $V'$ に$128$(あるいは2進数で$1000\,0000_2 $)を加えたものとして表現されます。

つまり、$V = V' + 128$ または$ V = V' + 1000\,0000_2$。

2の補数表現への変換

通常の2の補数表現へ変換するには、特殊な表現から128($1000\,0000_2$)を引きます。

$V' = V - 128$または$V' = V - 1000\,0000_2$

MSBの反転

MSBを反転するということは、数値から$1000\,0000_2$(128)を引くか、加えることと等価です。なぜなら、MSBが1の場合は1を0に反転(-128する)、MSBが0の場合は0を1に反転(+128する)からです。

したがって、MSBの反転は以下の操作に等しいです:

  • MSBが1の場合(つまり $V$が128以上の場合)、$ V' = V - 1000\,0000_2 $。
  • MSBが0の場合(つまり $V$が127以下の場合)、$ V' = V + 1000\,0000_2$。

証明

MSBの反転が128の加算または減算と等価であることを考えると、この操作は常に特殊な表現を標準的な2の補数表現に変換します。

  • $V $が128以上の場合、MSBは1です。したがって、MSBを反転すると$ V - 128 $になります。これは2の補数表現における負の値に相当します。
  • $V $が127以下の場合、MSBは0です。したがって、MSBを反転すると $V + 128$になります。しかし、$ V $が127以下であるため、この加算はオーバーフローを引き起こし、結果として128を引くことになります。これは2の補数表現における正の値に相当します。

したがって、MSBのみを反転する操作は、特殊な8ビットの「ゲタ履き数」を標準的な8ビットの2の補数表現に変換するための有効な方法であることが証明されます。


$\dagger$:符号無しの定義は0以上の正の整数のみを扱うデータ型であるため、正しくはゲタ(8'h80)履き数


左矢前のブログ 次のブログ右矢

posted by sakurai on January 16, 2024 #734

前項の矛盾解消案を示します。

. 主機能フォールトは100%検出され(修理されない)ため、レイテントにならないとの立場
この矛盾点は解消できない。

  1. 主機能フォールトは100%検出され修理されるため、レイテントにならないとの立場
    この矛盾点は主機能も修理系であると変更する。

  2. 主機能フォールトは、100%検出されてもレイテントになるとの立場
    この矛盾点は1.と同様LFとなるため、矛盾は解消できない。

条件1及び3はどうしても矛盾が解消できないため、極端な条件

「車両に修理人及び全ての故障に対応可能なスペアパーツを搭載している」

という条件を設け、条件2.の矛盾を解消しました。

従って2.の矛盾解消はいわばIFはMPFフォールトしないという仮定です。これを現実的にするためにありうるシナリオを考えたのがRAMS 2022論文です。それは以下のような仮定です。

  1. IFが運転中にフォールトする。MPF detectedなので車両はFTTI中に安全状態に移行する。
  2. IFがフォールトしているため、IFが冗長構成でない限り運転の継続は不可能。すなわち時間経過は無い=露出時間はゼロとみなされる。
  3. 通常は速やかに(年単位放置でも構わないが)修理工場に運ばれるが、E/Eシステムは修理まで電源オフであるため、再故障しない。すなわち時間経過は無い=露出時間はゼロとみなされる。
  4. 修理中はE/Eシステムは電源オフである。すなわち時間経過は無い=露出時間はゼロとみなされる。
  5. 修理完了後にAs good as newとして運用される。

このシナリオによれば、

  • IFのフォールト中の期間はFTTIを例外として露出時間はゼロであり、新品に交換された後に時間が経過する。
  • よって、車両に実際に修理人とスペアパーツを搭載して運用しなくても、それと同等と見なすことが可能。
  • 例外的なFTTI中のSMのフォールトは同時故障確率がゼロであることからゼロとみなす。

さて、上記からIFが(detectedの場合は)MPFフォールトしない前提であるため、PMHFのSPF/RF項だけが残り、IFの先故障によるDPF項はゼロとなります。従って、PMHFのDPF項は$\frac 1 2$が残ることになります。結論として1st edition/2nd editionのDPFの$\frac 1 2$は、SM1の先故障によるDPF確率だけをカウントするという意味で正しかったわけです。

図104.2
図104.2 1st edition規格第1式(引用)

一方で、1st editionのうち「故障順序によらない」場合の式は"MPF,detected"を加えている点で$\frac 1 2$が無いことから誤っています。2倍である理由は、DPFに関してSM1の先故障とIFの先故障の2つの場合を加えているためであり、上記のとおり、IFの先故障はカウントせずSM1の先故障のみをカウントするのが正解です。

図105.2
図105.2 ISO 26262 1st edition Part 10 第3式

左矢前のブログ 次のブログ右矢

posted by sakurai on January 15, 2024 #733

過去記事において、レイテントフォールトを取り上げました。1st SMにより検出されたフォールトはMPF detectedとなるが、このフォールトは、修理されるのか修理されないのかのどちらだろうかという、大変良い疑問です。

疑問については過去記事を見て頂くとして、以下にその回答を引用します。

  1. 主機能フォールトは100%検出され(修理されない)ため、レイテントにならないとの立場
    検出されても修理されないならば、いつかSMのフォールト発生によりDPFとなる。これはPMHF式のSMが、MPF detectedであっても検出周期内ではレイテントとなることからも分かる。よってレイテントフォールトとなることから前提と矛盾する。
  2. 主機能フォールトは100%検出され修理されるため、レイテントにならないとの立場
    修理されるのでDPFとならない。ところが、PMHF式は式の前提から、主機能は非修理系であり、PMHF式の前提と矛盾する。
  3. 主機能フォールトは、100%検出されてもレイテントになるとの立場
    上記議論から、100%検出されても修理されなければレイテントとなるが、故障分類フローではMPF detectedとMPF latentを明白に分けているため、故障分類フローと矛盾する。また、LFMの定義にはMPF detectedは除かれているため、LFMの定義とも矛盾する。

どの立場を取っても矛盾するということは、規格内部に矛盾があることを意味します。

と回答しました。すなわち、どのように考えても矛盾するというのが結論です。

しかしながらその後、矛盾を解消する提案を論文として投稿し、RAMS 2022に採択されました。

矛盾の解消案は以下のとおりです。

  1. の矛盾点は解消できない。MPF detectedとなっても修理されない状態で運転を継続すれば、SMのフォールトとの合わせ技でVSGとなるから、それはLFと同じである。
  2. の矛盾点は主機能も修理系であると変更する。ただしその修理はあたかも車両に修理人及びスペアパーツが搭載されているかの如く、瞬時に行われ運転は継続可能。これはIFが絶対にMPFフォールトしないのと同値である。これならLFMとも矛盾は生じない。
  3. の矛盾点は1.と同様LFとなるため、矛盾は解消できない。

RAMS 2022採択論文においてありうべきシナリオを検討したので、それを示します。


左矢前のブログ 次のブログ右矢

posted by sakurai on January 12, 2024 #732

Digilent Adeptの利用

Vivadoは開発システムのため、当然ビットストリームファイルを書き込むことが可能ですが、スタンダロンの書き込みツールがあります。それがDigilent Adeptです。これはFlashへの書き込みはできないようですが、SRAMにネットまたはUSB経由で書き込むことが可能です。

図%%.1
図732.1 Digilent Adept

左矢前のブログ 次のブログ右矢

posted by sakurai on January 11, 2024 #731

CmodA7toPMODボード

基本的には過去記事に対してボードをCmodA7ボードに変更したものです。 DigilentからCmodA7ボードを購入しました。このボードは(弊社開発の)PMOD変換ボードは必要となりますが、総額では安くSpace Invadersを動かすことができます。

図%%.1
図731.1 Cmod A7ボード

周辺インタフェースボード等

Space Invadersを動作させるには、CmodA7ボードの他に必要なものは以下のとおりです。

CmodA7-35ボードへの移植

Arty-35とFPGAアーキテクチャが同じであり、何も変更せずにそのままで動作しました。


左矢前のブログ 次のブログ右矢

Pongの開発 (18)

posted by sakurai on January 8, 2024 #730

Pongの完成

いままでのV5/V6の評価を含めて判明しているところまでをまとめます。

  • XADCのクロックが100MHz推奨と書かれていたのをそのまま100MHzを入力したが、最低入力周波数である8MHzまで落としたほうが良い。
  • XADCの設定画面においても8MHzとしたほうが良い。
  • V5/V6共に画面斜め縞が出る。これはXADCのクロックを停止しても出ている。
  • V5はさらにポップノイズ雑音が出る。
  • V6において+3.3Vに電解コンデンサー10uFを付加したところ、電源のノイズが消えた。電源ノイズが画面に表れていたようだ。

図730.1に完成したPongを示します。画面ではわかりにくいですが、斜めの縞模様が流れています。今まであまり意識しなくてもたまたま問題にならなかったのですが、VGAはアナログ信号のため、ノイズ対策をきっちりとやらないと今回のようになることが分かりました。

図%%.1
図730.1 Pong完成画面

左矢前のブログ 次のブログ右矢

CmodA7toPMODの評価

posted by sakurai on January 5, 2024 #729

CmodA7toPMODV5/6のノイズ評価

それぞれのボードに部品を実装してノイズ評価を行いました。その結果以下のようなことが判明しました。

  • 改版後のV6でもV5と同様にノイズが乗る。主にXADCに供給していた100MHzクロックが原因のようだ。
  • 100MHzを落として8MHz程度にすると正しく動作し、かつスイッチONでのブー音が消えた。

図%%.1
図729.1 XADC外部クロックを8MHzに
  • スペースインベーダーはXADCを使用していないので、どちらのボードでも画面縞は発生しない。
  • 一方、XADCクロックを8MHzに落としても画面の斜め縞はV5/V6両方で発生する。
  • XADCへの供給クロックを8MHzに落とした(上記)だけではなく、XADCの内部動作クロック設定も8MHzにしたが、斜め画面縞は変わらず原因不明。

図%%.2
図729.2 XADC外部クロックを8MHzに

実験によるフィードバック

V6基板においてVRを実際にADCに接続してJTAG経由で測定したところ、ADC入力電圧値は0.208~0.9804Vとなりました。LTSpiceの値とほぼ一致する結果です。

設計計算の変化点をマーカで表示します。ピンク前記事との変化点であり、ブルーは最終結果としてソースコードに入れる値です。

  • VRの全角度は300°
  • VRの有効角はパラメータ化し、開始角a[°] (デフォルト値a=105)、範囲b[°] (デフォルト値b=90)
  • VRの全角度の際のADC入力電圧は測定結果より、0.2~0.98[V]

図%%.3
図729.3 レベルダイア

再設計計算

これらより、ADC入力電圧は開始角$a$の値を$V_\text{a}$、終了角$a+b$の値を$V_\text{a+b}$として、 $\require{color} \definecolor{pink}{rgb}{1.0,0.8,1.0} \definecolor{blue}{rgb}{0.8,0.8,1.0}$

  • $V_\text{L}=\colorbox{pink}{0.2}$, $V_\text{H}=\colorbox{pink}{0.98}$
  • $V_\text{range}=V_\text{H}-V_\text{L}=\colorbox{pink}{0.78}$
  • $V_\text{a}=\frac{V_\text{range}}{300}a+V_\text{L}$
  • $V_\text{a+b}=\frac{V_\text{range}}{300}(a+b)+V_\text{L}$

次にAD変換後のデータDは入力全範囲0~1[V]を4096分割する。開始角の値を$D_\text{a}$、終了角の値を$D_\text{a+b}$として

  • $D_\text{a}=4096V_\text{a}=\frac{4096V_\text{range}}{300}a+4096V_\text{L}=\colorbox{pink}{10.65}a+\colorbox{pink}{819.2}$
  • $D_\text{a+b}=4096V_\text{a+b}=\colorbox{pink}{10.65}(a+b)+\colorbox{pink}{819.2}$
  • $D_\text{range}=D_\text{a+b}-D_\text{a}=\colorbox{pink}{10.65}b$

一方、y座標の制約は以下のとおりであり、$y_\text{top}$(上限$y_\text{max}$+5%)と$y_\text{bottom}$(下限$y_\text{min}$-5%)の値でクリッピング。

  • $y_\text{min}=\colorbox{pink}{44}, y_\text{max}=\colorbox{pink}{219}, Paddle_\text{h}=\colorbox{pink}{26}$
  • $y_\text{bottom}=y_\text{min}-7=\colorbox{pink}{37}, y_\text{top}=(y_\text{max}-Paddle_\text{h})+7=\colorbox{pink}{200}$
  • $y_\text{range}=y_\text{top}-y_\text{bottom}=200-37=\colorbox{pink}{163}$

これらからy座標を求めると、ADCのデータを$D$とすれば、

  • $y=\frac{y_\text{range}}{D_\text{range}}(D-D_\text{a})+y_\text{bottom}=\frac{\colorbox{pink}{163}}{\colorbox{pink}{10.65}b}D-\frac{\colorbox{pink}{163}}{b}a-\frac{\colorbox{pink}{163}\cdot\colorbox{pink}{819.2}}{\colorbox{pink}{10.65}b}+\colorbox{pink}{37}\\ =\frac{\colorbox{pink}{244.9}}{b\ll4}D-\frac{\colorbox{pink}{163}}{b}a-\frac{\colorbox{pink}{12538}}{b}+\colorbox{pink}{37}=\frac{\colorbox{blue}{245}D-\colorbox{blue}{2608}a-\colorbox{blue}{200615}}{b\ll4}+\colorbox{blue}{37}$

y式中のシフトは固定小数点演算を行うために分母分子を16倍しているものです。さらに最小値$D_\text{a}$、最大値$D_\text{a+b}$で入力ADCデータのクリッピングを行います。

  • $D_\text{a}=\colorbox{pink}{10.65}a+\colorbox{pink}{819.2}=(\colorbox{blue}{170}a+\colorbox{blue}{13107})\gg4$
  • $D_\text{a+b}=\colorbox{pink}{10.65}(a+b)+\colorbox{pink}{819.2}=(\colorbox{blue}{170}(a+b)+\colorbox{blue}{13107})\gg4$

以上より、完成したBSVコードの変更点のみを以下に示します。

クリッピング値計算部分

            // 座標の下限-5%と上限+5%に対応するADC値の計算
            Bit#(20) adcMinValue = (170 * extendedA + 13107) >>4;     // Min = 10.65A + 819.2
            Bit#(20) adcMaxValue = (170 * (extendedA + extendedB) + 13107) >> 4; // Max = 10.65(A+B) + 819.2

ADCからy値計算部分

            Bit#(24) coordinate = ((zeroExtend(clippedAdcValue) * 245
                   - zeroExtend(extendedA) * 2608 - 200615 + 915)
                   / zeroExtend(extendedB) >> 4) + 37;

+915は途中計算がアンダーフローして値が最大値にならないように調整するものです。この例のように小数点演算において0をわずかに割った場合、負数は正の最大値となるため、非常に大きな誤差が起こります。

FSM中でのパドルの可動範囲$y_\text{min}=\colorbox{blue}{44}$、$y_\text{max}-Paddle_\text{h} + 1=219-26 + 1=\colorbox{blue}{194}$でクリッピングすることを忘れないように注意します。


左矢前のブログ 次のブログ右矢

posted by sakurai on January 4, 2024 #728

BSVに簡単に変換できるからC/C++が優位とは論理が反対です。それはC/C++の優位性が無いことを示すものです。また合成できない機能についてはBSVに関係のないC/C++の欠点です。

逆です。それらはC/C++の優位性が無いことを表すものです。もともとポインタや動的メモリ管理等は合成できないのがC/C++の欠点です。なのでC/C++の優位性はそれらを除く逐次処理です。ところがその部分は自動ステートマシン合成を用いて容易にBSVに移植できるので、結論としてC/C++の優位性はほぼなく、BSVの優位性だけが示されるのではないですか?

ChatGPT
ご指摘の通り、C/C++のハードウェア合成における逐次処理の部分がBSVに容易に移植できる場合、C/C++の特有の優位性は大きく減少する可能性があります。特に、以下の点を考慮すると、BSVの優位性がより顕著になります:

  1. ハードウェア特有の機能:
    BSVはハードウェア設計のために特化された言語であり、ハードウェアの並行処理、同期、タイミング制御などの機能を直接的に表現できます。

  2. 自動ステートマシンの合成:
    BSVはC/C++の逐次的なコードをステートマシンに変換する能力があり、これにより、C/C++の逐次処理の優位性が相対的に低下します。

  3. 高レベルの抽象化:
    BSVはハードウェアの動作をより高い抽象化レベルで記述でき、複雑なハードウェアロジックの実装を容易にします。

C/C++によるハードウェア合成の主な利点の一つである既存のコードベースの再利用は、ポインタや動的メモリ割り当てなどの合成不可能な特性を除けば、BSVによってカバーできる範囲が広がります。結果として、特に逐次処理に関しては、BSVによる合成がより効率的かつ適切な選択肢となる可能性が高まります。

これにより、ハードウェア設計におけるBSVの優位性が強調され、C/C++の利用が必要とされるケースは限定的なものになるかもしれません。


所感:
ChatGPTはこのように平気で誤った論理的結論を導出することがあることに注意が必要です。一方、考え方の幅を広げて貰うには最適なことからそのような目的で使うべきであり、結論を導いて貰うべきではありません。

BSVとC/C++の比較の結論としては、技術的にはBSVのほうが圧倒的に有利であり、一方非技術的には、例えば学習コスト、ユーザベース、ツールチェイン等の面でC/C++が有利と理解しました。


左矢前のブログ 次のブログ右矢