ログイン
ユーザ名:

パスワード:


パスワード紛失

新規登録
Main Menu
Tweet
Facebook
Line
:-?
(1) 2 3 4 »
スレッド表示 | 新しいものから 前のトピック | 次のトピック | 下へ
投稿者 スレッド
webadm
投稿日時: 2008-8-12 11:11
Webmaster
登録日: 2004-11-7
居住地:
投稿: 3084
Poorman's MSM5524
おじゃんくなR-1000の周波数カウンタ/時計を復活すべくMSM5524と機能互換なCPLDロジックを設計するプロジェクト。



優先順位:

1. 周波数カウンタと7セグメント蛍光表示管ドライブ機能
2. 時計機能
3. タイマー機能

蛍光表示管ドライブのための高耐圧オープンドレインドライバは外付けトランジスタかFETで代用する。

とりあえずシミュレーションレベルまでやる。そもそもデバイスに入るか謎。

webadm
投稿日時: 2008-8-13 5:51
Webmaster
登録日: 2004-11-7
居住地:
投稿: 3084
トップレベル
とりあえずトップレベルのブロック図を描いてみた。



MSM5524の信号名のそのままだが名前を付けるのは重要。

次ぎは各信号の役割と仕様を定義する。

入力信号

FIN
周波数カウンタ入力。受信周波数+中間周波数を1/10プリスケールしたものが入力される。受信周波数が0〜30MHzで中間周波数が455kHzの場合、FINには45.5〜2945.5kHzの範囲が入力される。

IOS1,IOS2
中間周波数選択入力。オリジナルMSM5524ではAM,FM用の中間周波数が選択可能。内部の周波数カウンタにロードされる初期値(中間周波数の2の補数)を選択する。本設計では中間周波数は455kHz固定とするため意味は無い。将来の拡張用。

XT1,XT2
基準周波数生成用クリスタル振動子接続端子。内部の各種タイミングを生成する基準周波数として3.2768MHzの水晶振動子回路を外付けする。

A,B
時刻設定入力。時計及びタイマー動作時に入力の組み合わせによって動作を選択する。

A=H,B=H 通常動作
A=L,B=L リセット(時計動作時はAM1:00、タイマー動作時はAM0:00)
A=H,B=L 分を1進める(時計動作時秒は通常動作)
A=L,B=H 時を1進める(統計動作時秒は通常動作)

A及びBはそれぞれフロントパネルのMINUTEとHOURタイムセットボタンに対応し押されるとHからLに入力が変化する。

A=H,B=LもしくはA=L,B=H状態が1.6秒以上続くと継続的に0.1秒毎に値を進める。

HOURSET
オリジナルの用途不明。R-1000ではこの信号は使用されていない。互換性のための予約。

S1,S2,S3
表示選択入力。

S1=H,S2=H,S3=H 時計表示
S1=L,S2=H,S3=H スリープタイマー表示
S1=H,S2=L,S3=H ONタイマー表示
S1=L,S2=L,S3=H OFFタイマー表示
S1=H,S2=H,S3=L AMラジオ周波数表示
S1=L,S2=H,S3=L FMラジオ周波数表示
S1=H,S2=L,S3=L SWラジオ周波数表示
S1=L,S2=L,S3=L 周波数カウンタ表示

S4
オリジナル用途不明。R-1000ではこの信号は使用されていない。互換性のための予約。

DIMMER
DIMMER入力。Hが入力されるとディスプレイ表示パルス幅が1/4になり輝度を下げる。

TIMEROUTOFF
TIMER出力禁止入力。Lの時にタイマー出力信号はHに固定される。

BLANKING
BLANKING入力。Hが入力されるとタイマー出力以外の出力信号ピンがハイインピーダンス(表示OFF)に固定される。

AC
オールリセット入力。Lが入力されると内部がリセット状態となる。

T1,T2,T3
オリジナル用途不明。R-1000では使用していない。互換性のために予約。

出力信号

STOPWATCH
STOPWATCH表示オープンドレイン出力。R-1000では不使用。互換性のために予約。

AMBCOUT
AM/BC表示オープンドレイン出力。時計及びタイマー動作時にはAM時刻で、周波数カウンタ動作時にはAMラジオ周波数選択時にONとなる。

PMFMOUT
PM/FM表示オープンドレイン出力。時計及びタイマー動作時にはPM時刻で、周波数カウンタ動作時にはFMラジオ周波数選択時にONとなる。

SEGA-G,POINT
7セグメント及び小数点表示オープンドレイン出力。

IO0-4
桁表示コモンイネーブル出力。負論理。ダイナミック表示期間のみアサートされる。

SIGNALOUT
オリジナル用途不明。R-1000では不使用。互換性のために予約。

TIMEROUT
タイマー制御出力出力。負論理。タイマー出力ON時のみアサートされる。

SLEEPOUT
スリープ制御出力。R-1000では不使用。互換性のための予約。


webadm
投稿日時: 2008-8-14 20:05
Webmaster
登録日: 2004-11-7
居住地:
投稿: 3084
FREQUENCY COUNTERブロック
オリジナルのFREQUENCY COUNTERブロック図を良くみると内部で更に1/8プリスケールをしている。

従って最小桁がkHz単位の場合ゲート期間は1/10プリスケールのままの時の8倍、すなわち8/100(0.08)secとなる。

CPLDに余裕があればもっと測定分解能を高めるために100Hzとか10Hz単位をカウントできるようにすると同時にフロントパネルのMINUTE/HOURボタンで表示桁をシフトして小数点以下のkHzを表示することも可能かもしれない。PLLなのでそのくらいまでロックしてそうな気がする。そうすると最新の通信型受信機並になる。これは後の楽しみにとっておこう。

オリジナルではカウンタプリセット値が入力信号によって選択可能だが今回はR-1000専用で良いので内部固定とする。455の二の補数がプリセット値となる。

以前にPoorman's Signature Analyzerでもあったようにカウント終了後(ゲートがOFF後内部PRESET信号アサート時)にプリセット値を入力する動作をする。プリセット信号がアサートされていない間は入力パルスでカウント動作を継続する。

カウンタの出力値は常時ラッチの入力として与えられておりカウント終了後(ゲートがOFF後内部LOAD信号アサート時)にラッチ内容が更新される。ラッチ内容は常に7セグメントデコーダー回路に出力される。

内部PRESET信号は当然ながら内部LOAD信号より後にアサートされる必要がある。どちらもゲートOFF期間にのみ変化する。共通の信号で良いような気もするが。

FREQUENCY COUNTERブロックの入出力信号は下図の通り。



FIN - トップレベルのFIN

CE - Controlブロックで生成されるCounter Enable入力

RESET - Controlブロックで生成されるreset入力

PRESET - Controlブロックで生成されるpreset入力

LOAD - Controlブロックで生成されるload入力

LATCH - 本ブロック内部のカウンタ値ラッチの出力

FREQUENCY COUNTERブロックの主要入出力信号のタイミング関係は以下の通りとする。



FINは非同期入力。CE信号がアサートされている間のみFIN信号を8分周した立ち上がりエッジで内部カウンタをインクリメントする。

PRESET信号の立ち上がりで、内部カウンタに中間周波数値の2の補数がロードされる。これによって内部カウンタにはFINの周波数から中間周波数を差し引いた値がカウントされる。

LOAD信号の立ち上がりで内部カウンタ値の内容を内部のカウンタラッチレジスタにロードする。

LATCH出力は常に内部カウンタラッチレジスタに保持された値を出力される。

RESET信号がアサートされると内部の8分周カウンタが0リセットされる。

FREQENCY COUNTERブロック内部の構成については一通りブロック間インターフェースをまとめた後で各ブロックについて詳細に検討する。

ちょっと見た限りだと、やはりPRESETとLOADはGATEの立ち下がりで兼用できそうな雰囲気ではある。すなわちCE信号を反転した信号の立ち上がりでPRESETとLOADをやってしまうという考え方もありである。実際にはカウンターのキャリー伝搬遅延とかがあるのでそんな単純に行かない気がするが(GATE信号がネゲートされた後にカウンタの出力が遅れて変化する可能性がある)。

オリジナルのMSM5524の内部ブロック図にこだわらずに考えれば、内部の3.2768MHzのクロックを基準にステートマシンでPRELOAD,CE,LOAD信号を生成しても良いが、他にも異なるタイミング生成が必要なのでとりあえずオリジナルのブロックを参考に組み立ててみることにする。
webadm
投稿日時: 2008-9-8 10:54
Webmaster
登録日: 2004-11-7
居住地:
投稿: 3084
CLOCK DIVIDERブロック
CLOCK DIVIDERブロックは外付け3.2768MHz水晶発振子を使って生成したクロック信号を分周し内部で使用する様々な周期のクロック信号を供給する。



XT1,XT2
外部3.2768MHz水晶発振子に接続。

C3200Hz
3.2678MHzを1024(2^10)分周した3.2kHzの表示スキャン用基準クロック出力。

C800Hz
C3200Hzを更に4(2^2)分周した内部基準クロック。入力信号デバウンサー、周波数カウンタ制御クロック生成に使用。

C10Hz
時計、タイマー設定信号生成用基準クロック。設定ボタンが1.6秒以上押されると10Hz単位で設定値がup/down更新する際に使用される。C800Hzを80分周したもの。

C1Hz
時計、タイマー更新用基準クロック。C10Hzを10分周したもの。

タイミングチャートは以下の通り。



webadm
投稿日時: 2008-9-14 23:10
Webmaster
登録日: 2004-11-7
居住地:
投稿: 3084
CONTROLブロック
CONTROLブロックは内部のカウンタ、時計を制御する様々な信号を生成する。



外部から入力されるスイッチ入力信号はC800HZのクロックでサンプルされ、デバウンス処理されたものが内部で使用される。



デバウンス処理されたA,B入力とC10Hz信号によってカウンタ、時計の時分調整用信号(TIMMADJ,TIMHADJ)が生成される。A,B入力信号のアサート期間が1.6秒(C10Hz 16サイクル)未満の場合には、C10HZで1サイクル分だけ対応する時分修正信号がアサートされる。1.6秒以上アサートされるとアサートされている間時分修正信号がアサートされる。これによって1.6秒以上A,Bスイッチを押すと以降0.1秒間隔で時分が進むことになる。



C800HZに同期して、周波数カウンタ制御のためのCE,RESET,PRESET,LOAD信号が生成される。ACデアサート後にRESET,PRESET,CE,LOADが順にアサートされる4つのステートを繰り返す。CEがアサートされる期間は8/100秒(C800HZ 64サイクル)である。それ以外は1/800秒のパルスとなる。



S1,S2,S3の外部入力信号はデバウンス後にC10Hzの立ち上がりに同期したカウンタセレクト信号(CS1,CS2,CS3)として出力される。



この当たりの内部動作に関してはMSM5524内部信号の詳細が明らかにされていないので迷いが多い。

カウンタ、時計、タイマーの制御に関してはいろいろやり方が考えられる。MSM5524はどうやら古い複数クロック信号による非同期回路になっている模様でCPLDとかではやっかい。とは言え現代のように高性能なPCと論理合成ソフトやシミュレーターなど無い時代に設計されたICなので同期設計とか望んでも無理な話。昔はみんな紙の上でロジックを設計し論理圧縮して、ICマスクを大きな紙にプリントアウトして広げて人間がチェックしていた時代である。

だいたいカウンタ、時計、タイマー回りのロジックがどうなっていたのかは想像できるがCPLDでそれをやろうとするとかなりタイミング的に問題が出るかもしれない。幸いに動作周波数が遅いので配置配線による遅延に比べれば微々たるものかもしれない。やってみないとなんとも。

本職の設計者ならこの程度は1日もかからずに設計してしまうのだろうけど、そこはそれ経験が無いのと知識が無いので、ボトムアップ的なフィードバックが後々あることを承知の上でのろのろと進めている次第。

MSM5524はOKIの半導体だけど、昔はOKIもOKITACという名前のミニコンピューターを作っていたコンピュータメーカーだった。マイコンが登場してからはIF-800というパソコンを出していたがOKIの頼みの綱である官公庁とか電電公社の一部で採用された以外は市販ではまったく売れず。そのうちフェードアウトしてしまった。当時は独自のRISC CPUチップを開発して巻き返しとか言っていたようだけど、そういう人達はさっさと辞めてしまったのか、その後半導体メーカーとしての力量は落ちる一方。最近では半導体事業そのものを売却するという動きもあるらしい。それ以前に戦前からの技術者虐め体質が抜けずにほとんどの技術者はとっくの昔に辞めてしまっているので中古設備の売却に近いのではないかと想像する。
webadm
投稿日時: 2008-9-16 5:20
Webmaster
登録日: 2004-11-7
居住地:
投稿: 3084
CLOCK TIMERブロック
おそらく一番複雑でロジック規模も大きいブロック。時計とタイマーカウンターそれにコンパレーター回路を含むCLOCK TIMERブロック。



オリジナルのMSM5524のブロック図では大まかな内部構成が書いてあるものの制御信号については想像するしかない。実際にはボトムアップで実現可能性のある内部ロジック構成を検討した上でそれに必要な外部インタフェースを決めた。

オリジナルのMSM5524にはあるが、R-1000では使用されていないスリープタイマーに関しても将来の拡張用に信号だけはアサインしてあるが今回は実装予定無し。R-1000で使われていないだけにそれに関する仕様は不明なところが多い。リセット機能はあるのかどうかとか最大60分までなのかとか。実装しないのでそのあたりの仕様はTBD。

入力信号はCLOCK DIVIDERブロックからのC10HZとC1HZのクロック信号とCONTROLブロックからのカウンタ選択信号(CS1,CS2,CS3)と時分修正信号(TIMMADJ,TIMHADJ)それにAC。

出力信号は

CLCOUNTER
時計カウンタ値(秒、分、時、AM/PM)出力。秒、分、時はそれぞれBCDで2桁、AM/PMは1ビット。

ONTIMER
ON TIMERカウンタ設定値(分、時、AM/PM)出力。分、時はそれぞれBCDで2桁、AM/PMは1ビット。

OFFTIMER
OFF TIMERカウンタ設定値(分、時、AM/OM)出力。分、時はそれぞれBCDで2桁、AM/PMは1ビット。

SLEEPTIMER
SLEEP TIMERカウンタ値(分)出力。BCD1桁。

ONCMPOUT
ON TIMERコンパレータ出力。

OFFCMPOUT
OFF TIMERコンパレータ出力。

SLEEPOUT
SLEEP TIMER満了出力。
webadm
投稿日時: 2008-9-17 10:16
Webmaster
登録日: 2004-11-7
居住地:
投稿: 3084
DISPLAYブロック
残るは表示出力信号を制御するDISPLAYブロックのみ。



ここにきて検討し忘れていた内部信号があるのを発見。

DIMMER入力信号によって蛍光表示管の表示ストローブパルスを1と1/4にDUTY比を切り替える必要がある。

実際の表示タイミング信号はすべてDISPLAYブロック内で生成するほうが同期がとれて都合が良いので、DUTY比の指定信号のみをCONTROLブロックから与えてもらうようにする。

よく考えると同じ信号でよさそうな気がするが独立しているのは何か隠された意味があるのだろうか?

蛍光表示管はLEDと違い放電現象を利用しているので表示制御のタイミングに固有のノウハウが必要な気もする。桁を切り替える際に間隔を空けるとか。

オリジナルの仕様が謎なので、このあたりは独自に試行錯誤して作るしかない。

オリジナルの表示スキャン間隔がどれくらいかわからない。現物で仮のダイナミック表示をさせて検討を付けるか、同じICが使用されている表示が故障していないFRG-7700とかを手にいれて測定してみるかしかない。たぶん実際に動かして調整した方が早いかもしれない。

そういえば蛍光表示管は日本人の発明品だ。現在もノリタケ伊勢電子の専売特許品。Webで一台から購入できるらしい。秋月とかでよく見かける液晶表示モジュールと同じ感覚で簡単にマイコンから制御できる2行表示モジュールとかあるらしい。そういうのを使えばもっと高機能なことができる。その場合はPICとかで制御した方が良いだろう。

webadm
投稿日時: 2008-9-18 13:18
Webmaster
登録日: 2004-11-7
居住地:
投稿: 3084
RTLスケルトン入力
トップレベルのブロック分けが終了したのでRTL記述の段階に入る。

Signature Analyzerの時のようにQuartus IIでtemplateを使ってRTLスケルトンを入力してコンパイル。

top.v: topモジュール

module top(fin, ios1, ios2, xt1, xt2, a, b, hourset, s1, s2, s3, s4, dimmer, timeroutoff, blanking, ac, t1, t2, t3,
stopwatch, ambcout, pmfmout, sega, segb, segc, segd, sege, segf, segg, point, io, signalout, timerout, sleepout);

// Input Port(s)
input fin, ios1, ios2, xt1, a, b, hourset, s1, s2, s3, s4, dimmer, timeroutoff, blanking, ac, t1, t2, t3;

// Output Port(s)
output stopwatch, ambcout, pmfmout, sega, segb, segc, segd, sege, segf, segg, point, signalout, timerout, sleepout;
output [4:0] io;

// Inout Port(s)
output xt2;

// Parameter Declaration(s)

// Additional Module Item(s)
// A net models connectivity in a design.

// Scalar net
wire ce, reset, preset, load;
wire c3200hz, c800hz, c10hz, c1hz;
wire duty, strobe, timmadj, timhadj;
wire oncmpout, offcmpout, sleep;

// Unsigned vector
wire [19:0] fcounter;
wire [2:0] cs;
wire [16:0] clcounter, ontimer, offtimer, sleeptimer;

// Nets may be declared with many different types with different
// electrical characteristics:

// wire/tri Basic connection w/ typical electrical behavior

// supply1/supply0 Tied to VCC/GND

// tri1/tri0 Default to 1/0 if left undriven

// wor/trior Multiple drivers resolved by OR

// wand/triand Multiple drivers resolved by AND

// Basic module instantiation
fc fc(ac, fin, ce, reset, preset, load, fcounter);

cd cd(ac, xt1, xt2, c3200hz, c800hz, c10hz, c1hz);

control control(a, b, dimmer, ac, c800hz, c10hz,
ce, reset, preset, load, duty, strobe, timmadj, timhadj);

ct ct(ac, {s3,s2,s1}, timmadj, timhadj, c10hz, c1hz,
clcounter, ontimer, offtimer, sleeptimer, oncmpout, offcmpout, sleep);

disp disp(c3200hz, {s3,s2,s1}, fcounter, clcounter, ontimer, offtimer, sleeptimer,
oncmpout, offcmpout, sleep, duty, strobe, ac, blanking,
stopwatch, ambcout, pmfmout, sega, segb, segc, segd, sege, segf, segg, point,
io, signalout, timerout, sleepout);

endmodule


fc.v: FREQUENCY COUNTERモジュール

module fc(fin, ce, reset, preset, load, fcounter);

// Input Port(s)
input fin, ce, reset, preset, load;

// Output Port(s)
output reg [19:0] fcounter;

// Inout Port(s)

// Parameter Declaration(s)

// Additional Module Item(s)

endmodule

cd.v: CLOCK DIVIDERモジュール

module cd(xt1, xt2, c3200hz, c800hz, c10hz, c1hz);

// Input Port(s)
input xt1;

// Output Port(s)
output xt2, c3200hz, c800hz, c10hz, c1hz;

// Inout Port(s)

// Parameter Declaration(s)

// Additional Module Item(s)

endmodule

control.v: CONTROLモジュール

module control(a, b, hourset, s1, s2, s3, s4, dimmer, timeroutoff, blanking, ac, c800hz, c10hz,
ce, reset, preset, load, duty, strobe, blankingout, acout, cs, timmadj, timhadj);

// Input Port(s)
input a, b, hourset, s1, s2, s3, s4, dimmer, timeroutoff, blanking, ac, c800hz, c10hz;

// Output Port(s)
output ce, reset, preset, load, duty, strobe, blankingout, acout, timmadj, timhadj;
output [2:0] cs;

// Inout Port(s)

// Parameter Declaration(s)

// Additional Module Item(s)

endmodule

ct.v: CLOCK TIMERモジュール

module ct(ac, cs, timmadj, timhadj, c10hz, c1hz,
clcounter, ontimer, offtimer, sleeptimer, oncmpout, offcmpout, sleepout);

// Input Port(s)
input ac, timmadj, timhadj, c10hz, c1hz;
input [2:0] cs;

// Output Port(s)
output oncmpout, offcmpout, sleepout;
output [16:0] clcounter, ontimer, offtimer, sleeptimer;

// Inout Port(s)

// Parameter Declaration(s)

// Additional Module Item(s)

endmodule

disp.v: DISPLAYモジュール

module disp(c3200hz, cs, fcounter, clcounter, ontimer, offtimer, sleeptimer,
oncmpout, offcmpout, sleep, duty, strobe, ac, blanking,
stopwatch, ambcout, pmfmout, sega, segb, segc, segd, sege, segf, segg, point,
io, signalout, timerout, sleepout);

// Input Port(s)
input c3200hz, oncmpout, offcmpout, sleep, duty, strobe, ac, blanking;
input [2:0] cs;
input [19:0] fcounter;
input [16:0] clcounter, ontimer, offtimer, sleeptimer;

// Output Port(s)
output stopwatch, ambcout, pmfmout, sega, segb, segc, segd, sege, segf, segg, point, signalout, timerout, sleepout;
output [4:0] io;

// Inout Port(s)

// Parameter Declaration(s)

// Additional Module Item(s)

endmodule

ここまで入力している間にもっとインタフェース信号数を減らせることに気づく。それはまた後日検討しよう。

RTLスケルトンをコンパイルしてRTL Viewerでトップブロックを表示すると



もう出来た気分(´ー` )

あとは各ブロックの中身のRTLを記述すればよい。
webadm
投稿日時: 2008-9-18 22:49
Webmaster
登録日: 2004-11-7
居住地:
投稿: 3084
RTL: FREQUENCY COUNTER
いよいよ各ブロック内部のRTL設計を行う。



FIN入力は1/8プリスケーラーを経て5桁分の同期BCDカウンタのクロックとして供給される。

1/8プリスケーラーはCEがアサートされている場合のみ動作する。

同期BCDカウンタのキャリー出力はそれぞれ一つ上の桁の同期BCDカウンタのイネーブルに入力されキャリーが伝搬される。

RESETがアサートされると1/8プリスケーラーとその出力はリセットされる。

PRESETがアサートされると5桁の同期BCDカウンタに対する非同期データセットが行われる。設定されるデータはBCDで455の二の補数表現である。

LOADの立ち上がりエッジで現在の同期BCDカウンタ出力値で出力レジスタ値を更新する。

同期BCDアップカウンターをサブモジュールとして新たに作成しfcモジュールでインスタンス化して使用するようにした。

sbuc.v: 同期BCDアップカウンターモジュール

module sbuc
(
input clk, ci, preset,
input [WIDTH-1:0] data,
output reg [WIDTH-1:0] count,
output reg co
);

parameter WIDTH=4, LIMIT=4'h9;

always @ (posedge clk or posedge preset)
begin
if (preset)
count <= data;
else if (ci)
begin
if(count == LIMIT)
count <= {WIDTH{1'b0}};
else
count <= count + 1'b1;
end
end

always @ (count or ci)
begin
if(count == LIMIT && ci)
co <= 1'b1;
else
co <= 1'b0;
end

endmodule


fc.v: FREQUENCY COUNTERモジュールRTLインプリメンテーション

module fc(ac, fin, ce, reset, preset, load, fcounter);

// Input Port(s)
input ac, fin, ce, reset, preset, load;

// Output Port(s)
output reg [19:0] fcounter;

// Inout Port(s)

// Parameter Declaration(s)
parameter [19:0] iv=(~20'h455)+1'b1;
// Additional Module Item(s)

reg [4:0] ps_cnt;
wire [3:0] c1, c10, c100, c1000, c10000;
wire co1,co10,co100,co1000,co10000;

// Basic module instantiation
sbuc fc1(ps_cnt[4], 1'b1, preset, iv[3:0], c1, co1);
sbuc fc10(ps_cnt[4], co1, preset, iv[7:4], c10, co10);
sbuc fc100(ps_cnt[4], co10, preset, iv[11:8], c100, co100);
sbuc fc1000(ps_cnt[4], co100, preset, iv[15:12], c1000, co1000);
sbuc fc10000(ps_cnt[4], co1000, preset, iv[19:16], c10000, co10000);

always@(posedge fin or posedge reset or negedge ac)
begin
if(!ac || reset)
ps_cnt <= 0;
else if(fin && ce)
ps_cnt <= ps_cnt + 1'b1;
end

always@(posedge load or negedge ac)
begin
if(!ac)
fcounter <= 0;
else if(load)
fcounter <= {c10000, c1000, c100, c10, c1};
end

endmodule


これをコンパイルしてRTL Viewerで見るとだいたい期待していた通りのロジックが出来上がっている。


webadm
投稿日時: 2008-9-19 5:14
Webmaster
登録日: 2004-11-7
居住地:
投稿: 3084
RTL: CLOCK DIVIDER
次ぎはCLOCK DIVIDERブロックのRTL設計。



最も単純だが、FPGAやCPLDで水晶発振子を直接駆動する発信回路というのだけがくせ者である。ディスクリート回路ではバッファ無しのインバーターがひとつあればいいのだが、FPGAやCPLDで単純に外部からの入力を論理反転して出力するだけの記述だと、配置配線によって不確定数のバッファが挿入されることになる。

一応デバイスベンダー固有のIOプリミティブを使用することによって入出力ピンに直接接続されているIOブロック内のインバーターを使うことは可能だがうまく発振してくれるかは保証の限りではない。

うまくいかない場合には、外付けのディスクリートのインバーター回路を設けてそれで発振をさせてその出力をXT1に入力するという手もある。

cd.v: CLOCK DIVIDERインプリメンテーション

module cd(ac, xt1, xt2, c3200hz, c800hz, c10hz, c1hz);

// Input Port(s)
input ac, xt1;

// Output Port(s)
output xt2, c3200hz, c800hz;
output reg c10hz, c1hz;

// Inout Port(s)

// Parameter Declaration(s)

// Additional Module Item(s)
reg [9:0] div1024;
reg [1:0] div4;
reg [3:0] div16;
reg [2:0] div5;
reg [3:0] div10;

assign c3200hz = div1024[9];
assign c800hz = div4[1];
assign xt2 = ~xt1;

always@(posedge xt2 or negedge ac)
begin
if(!ac)
div1024 <= 0;
else if(xt2)
div1024 <= div1024 + 1'b1;
end

always@(posedge c3200hz or negedge ac)
begin
if(!ac)
div4 <= 0;
else if(c3200hz)
div4 <= div4 + 1'b1;
end

always@(posedge c800hz or negedge ac)
begin
if(!ac)
div16 <= 0;
else if(c800hz)
div16 <= div16 + 1'b1;
end

always@(posedge div16[3] or negedge ac)
begin
if(!ac)
begin
div5 <= 0;
c10hz <= 0;
end
else if(div16[3])
begin
if(div5 == 6'd5)
begin
c10hz <= ~c10hz;
div5 <= 0;
end
else
begin
div5 <= div5 + 1'b1;
end
end
end

always@(posedge c10hz or negedge ac)
begin
if(!ac)
begin
div10 <= 0;
c1hz <= 0;
end
else if(c10hz)
if(div10 == 4'd5)
begin
c1hz <= ~c1hz;
div10 <= 10;
end
else
begin
div10 <= div10 + 1'b1;
end
end

endmodule


コンパイルした結果のネットリストは以下の通り。ちょっと見た目は違うけどバイナリで分周する部分はカスケードになっているし、どうしても2カ所5分周が必要になるのでそれも期待通り。もっとエレガントで綺麗な記述方法があるかもしれない。


(1) 2 3 4 »
スレッド表示 | 新しいものから 前のトピック | 次のトピック | トップ

投稿するにはまず登録を
 
ページ変換(Google Translation)
サイト内検索