MastHead

M系列で White Noise の生成


[31,28]g の M-Sequence でホワイトノイズを生成してみました。  2^31-1 の PRBS (Pseudo-Random Binary Sequence) になります。
かなり性質の良いノイズができました。

電線で回路を作っていると時間がかかるので、8051 のチップを使って簡単なプログラムを書いて動作させました。


全体が 31bit のシフトレジスタをシミュレートし、タップを 28 に取った M 系列シフトレジスタです。  M-系列のタップ位置については[以前の記事]を参考にしてください。
適当にプログラムして、まずアイパターンを出してみます。 右の図です。 これはわざと立ち上がりをなまらせて、縦の線がよく見えるようにしています。

まあすなおに出ました。 MPU のハードウェアクロックは 25MHz なのですが、シミュレートしたシフトレジスタのクロックはプログラムステップの分だけ遅くなりますので 763kHz 程度になっています。 (ですので、出力波形の 1 や 0 の最少区間は 1.3us です) またこの原信号の振幅は 3.2V です。

スペクトルを見てみます。 クロックの 1/4 程度がよく見えるようにスパンを 250kHz に取っています。 縦軸は、中央が -30dBV で、一目盛り 10dB です。 窓は Hanning にしています。

フラットで、きれいなホワイトノイズになっています。
ちょっと聞いてみてください。
これです ==>


高い方はどうなっているでしょうか。 スパンを 2.5MHz に広げてみます。
760kHz のところで落ち込んでおり、ここより 1/4 程度のところまで使えることが分かります。

低い方はどうなっているでしょうか。 31 ビットですから、 760kHz の 2^31 分の 1 である 0.00035Hz 位まで伸びているはずです。 スパンを 100Hz にした右の図ではもちろん見えませんね。

オーディオ帯では問題なく使えます。 ただし、オーディオではホワイトは、 Δf/f を同じにすると高い周波数で Δf が大きくなっていきますから耳には高い周波数が大きく聞こえます。 高い方を 1/√f で (-3dB/Oct. で) 落としこんだピンクノイズを使うときもあります。

え? どうしてももっと低いところまで見たい?
右の図はスパンが 1Hz です。 1目盛り 0.1Hz ですね。 これを取るのはとても時間がかかるんですよ。
31 ビットでは高級すぎるときはもっとビット数を落としてもいいでしょう。
試しに 7 ビットにしてみましょうか。 [7,6]g で作ってみました。

右の図はスパン 50kHz で見ていますが、なんか変ですね。 明らかに特定の周波数成分が見えます。 
聞いてみましょうか ==>

ぜんぜんダメです。 シミュレーションのクロックは 1.53MHz ですので、2^7-1 の 127 で割ると 12kHz になります。 私の耳には聞こえません。

こうして考えると、下限の周波数で 1/10 Hz 程度をねらえばいいことが分かります。 キャリアが 700kHz とすると、23 ビットほどで十分です。


------
下のコードが今回実験で使ったものです。 P3.3 から出力を取っています。 P3.2 はオシロを同期させるための信号です。 JC のインストラクションはジャンプしないときは 2 サイクルしかとらないので NOP を入れています。
今回使ったチップは Silicon Lab の C8051F310 というもので、安価に入手できます。 開発キットも容易に手に入ります。  チップのスペックはこちらです==> C8051F31x
実際に使用するのならば出力に 20kHz 以上を通さないフィルタを入れる必要があります。
===== 8051 Code for [31,28]g and [7,6]g =====
       (前略)
       mov    r0,#2      ;set seed
       mov    r1,#0
       mov    r2,#80h
       mov    r3,#0
       mov    r7,#82h  ;bits 1 and 7 for [7,6]g
       mov    r6,#0
       mov    r5,#20h  ;bit 29 for [31,28]g
       mov    r4,#1     ;bit 1
       mov    a,#2
       clr    c
      ;jmp    lp1           ;activate this line for [7,6]g

       ;31 bit M Seq
lp:    setb   p3.2 ;sync
       clr    p3.2

       ;shift all 31 bits
       mov    a,r0
       rlc    a
       anl    a,#0ffh-1 ;length=31
       mov    r0,a
       mov    a,r1
       rlc    a
       mov    r1,a
       mov    a,r2
       rlc    a
       mov    r2,a
       mov    a,r3
       rlc    a
       mov    r3,a
       jc     setbit

       ;no carry case
       nop                 ;1 clock compensation
       mov    a,r3
       xrl    a,r6        ;nop
       mov    r3,a
       mov    a,r0
       xrl    a,r6        ;nop
       mov    r0,a
       setb   p3.3        ;set output
       jmp    lp

       ;carry case
setbit: mov   a,r3
       xrl    a,r5        ;flip bit 29 for carry
       mov    r3,a
       mov    a,r0
       xrl    a,r4        ;set bit 1 for carry
       mov    r0,a
       clr    p3.3        ;clear output
       jmp    lp


       ;7 bit M Seq
lp1:   setb   p3.2
       clr    p3.2
       rlc    a
       anl    a,#0ffh-1
       jc     setbit1
       nop
       xrl    a,r6
       setb   p3.3
       jmp    lp1

setbit1:
       xrl    a,r7
       clr    p3.3
       jmp    lp1
================== code end ===================


[余談]
この 2^31-1 のときに極端に低い周波数まで伸びているというのは、伝送回路を考えるときは問題になります。 近いうちにこれについて考えてみます。


[余談2]
M-系列で Carry bit を使いましたが、これの性質をちょっと調べておきましょう。 ホワイトノイズで大切なのは周波数に関する情報です。 
先人の知恵をお借りします。 Cal Tech の Titsworth という方の計算によると、クロックを ωc、シフトレジスタの段数を n としたとき、最低要素周波数はωc/(2^n-1) になって、そこから上に ωc/(2^n-1) の間隔でコンポーネントが連なっており、それぞれのコンポーネント(周波数ω)の相対振幅は

         Sin^2(πω/ωc) / (πω/ωc)^2

で表されるとのことです。  ちょっとグラフにしてみますとこんな風です。 0.1Hz までは要素をプロットし、それ以上は連続線で表しました。



実験結果と合っていますね。
私見ですが、直流分もあるはずです。 31 ビットの 1 の連続は一巡の間に 1 回だけ出てきますが、0 の 31 回連続は出てきません。 30 ビットの 1 の連続は出てきませんが、0 なら 1 回出てきます。 (29 ビット以後はどちらも 1、2、4、8... と同数出てきます。) ですから + の方が一巡の長さの 1/(2^31-1) だけ多くなります。 上の図の 0dB に当たる量です。

-----------------
[M-系列、関連記事]
- NRZ 信号と PRBS とカップリング
- M-系列のタップ位置の表とプログラム
- M系列のレジスタを0で始める、ガロアとフィボナッチを入れ替える