ログイン
ユーザ名:

パスワード:


パスワード紛失

新規登録
Main Menu
Tweet
Facebook
Line
:-?
« 1 2 (3) 4 »
スレッド表示 | 古いものから 前のトピック | 次のトピック | 下へ
投稿者 スレッド
webadm
投稿日時: 2008-2-9 11:34
Webmaster
登録日: 2004-11-7
居住地:
投稿: 3095
だいたい動くことを確認
一カ所ステートマシンの出力信号の式が間違っていた点を除けばほぼ大きな問題は無いとみた。

もうこれで意図した通り動くと思われるで厳密にテストベンチでいろんなケースを試すよりは実際に装置を組んで実機で試してみたほうが良いかもしれない。

シミュレーションで確認していないのはテスト信号出力だけど、これは当面使う予定は無い。

とりあえずHP3456AのROMシグネチャの確認をしたい。新しく作ったROM基板が間違いないか確認したいのである。そうすれば故障原因は他にあるということで切り分けができる。

当初実機は1万年カレンダーを流用と考えていたが、あれは結構がさばるので実際に測定しようと思うと置き場所に困る。

この際、専用の基板をユニバーサルボードでこしらえて、LEDや入力信号コネクタやスイッチをつけて、そこにトラ技付録のMAX II基板をのせるとしよう。LEDは余っているし。

回路図を描いて部品を買って半田付けするだけである。
webadm
投稿日時: 2008-2-9 11:25
Webmaster
登録日: 2004-11-7
居住地:
投稿: 3095
Re: ステートマシンの問題(その1)
例の状態値レジスタが4つ生成されている件は、コンパイル結果のState Machinesを見ることによって、One Hotステートマシンが生成されているのに間違いないことが判明。



S00の時はすべて0で、他はどれか2つが1で残りは0という組み合わせらしい。

いずれの状態に遷移しても同時に変化するビットは2ビットだけということになるのでOne Hotに間違いない。

これはこれでクローズ。
webadm
投稿日時: 2008-2-9 5:23
Webmaster
登録日: 2004-11-7
居住地:
投稿: 3095
Re: ステートマシンの問題(その1)
このプロジェクトはもとはと言えば、おジャンクなHP3456Aの故障原因を突き止めるためにサービスマニュアルにあるシグネチャアナライザを使った故障診断を行うのが目的だった。

で以前から気になっていたのだが、HP3456AのサービスマニュアルのROMシグネチャの測定のところでプローブを+5Vに接続して測定した場合にシグネチャ値は0003になる、と書いてある。

HP3456AのROMシグネチャの測定ではROMアドレス空間である上位32KBの時にアサートされるA15をSA START/STOP信号として使用する。SA CLOCKはシステムクロックで6MHzを4分周した1.5MHzである。ROMシグネチャアナリシス中はCPUはフリーランするのでSA START/STOPのパルス周期は65KB分、すなわち65536サイクルということになる。

実は疑似乱数生成回路があっているか確かめるためにC言語で等価なプログラムを書いて65536サイクル分data=1固定でシグネチャ値を生成したらいくつになるか調べてみたら、64KB目には初期値0に戻ってしまうことがわかった。これだと違う。本当は0003になって欲しいのだが。

今回の回路はHP5004Aの回路図を苦労して読み取って等価な回路にしたつもりだったのだが、何か違うのだろうか悩んだ。しかしやはり同じだという結論しか出てこない。

ふと今回のシミュレーション結果で計測終了時にシフトレジスタが0にクリアされた直後にヒゲでシフトレジスタが一回動作してしまい初期値が0000ではなく0001になってしまうことが発覚してふと気づいた。

初期値が0000ではなく0001なら65536サイクル後にシグネチャ値はいくつになるのだろうか?

やってみたら見事に0003になった。

つまりこれはHP5004Aの仕様そのままであるということだ。

オリジナルの回路を見てもやはりヒゲは出てしまう。ヒゲも仕様のうちに含まれていたのだったのだ。

なのでこれはこのままで良いことにする。

他に気づいた点がいくつもあるのでそちらをなんとかしよう。
webadm
投稿日時: 2008-2-8 22:51
Webmaster
登録日: 2004-11-7
居住地:
投稿: 3095
ステートマシンの問題(その1)
ステートマシンからのCLEAR出力が繰り返しトグルする原因が判明した。

仕様段階では正論理で考えていたCLEAR信号を実装時に負論理にしたのだが、その時に頭で考えたドモルガンの定理による論理式の書き換えが間違っていた...orz

仕様では正論理で

CLEAR = (STOP & !CLOCK) | RESET

だったのをCLEARとRESETを負論理に書き換えた際に

clear = (!stop & clock) & reset

としていたのだが、本来は

clear = (!stop | clock) & reset

であった。

このように修正すると異常なトグル動作は無くなったが別の問題が発覚。



計測終了時のCLEARパルス幅が予想より短くて、直後にSHIFTパルスがヒゲのように余分に出てしまっている。このためせっかくリセットされたシフトレジスタが誤動作してしまい、初期値が0でなくなってしまっている。

仕様上でCLEARパルスが半クロックサイクルしか出ないようにしたのが良くないので、初期状態ではCLEARはアサートしたままに変更したほうが良いかもしれない。

それにして計測終了時に状態値レジスタが全部OFFになってしまうのは何故だろう? もしかしてそのままバイナリなのか?

しかし何故4ビットある?
webadm
投稿日時: 2008-2-8 22:13
Webmaster
登録日: 2004-11-7
居住地:
投稿: 3095
波形入力(Quartus Simulator)でやってみた
もしかして一発でOKかもしれないという思いから手っ取り早くその答えを知るために波形入力でシミュレーションをやってみた。

後で同じ波形を与えるテストベンチテンプレートを自動作成できるので慣れているこの方法がやりやすい。

とりあえず4桁のLEDが全部表示し終わる程度の時間をシミュレーションすることにし、SA_CLOCK入力はHP5004Aの仕様上限と同じ25MHzを与え、RESET入力のアサートとデアサート、それにSA_START/STOPのパルスを65536クロック周期で与える。その間はSA_DATAは1のまま。

おそらくLED表示コントローラー部分は何の問題も無く動作するだろう、以前に1万年カレンダー時計で培った回路なので。他は動く事は動くだろうけど疑問符がつくことは否めない。

やってみたら、回路が小さいので意外とシミュレーションが短時間で終わった。

そして結果をみたら、やはり表示コントローラーはまじめに動作しているくさい。しかし次ぎの瞬間、驚愕の事実が発覚。



まずステートマシンがしょっぱな誤動作している...orz

いきなりS00,S01どちらも1になっている。よく考えたらRESETがアサートされたらS00に戻るようにしていたのにそこからして意図した動きになっていない。

S00がONになりっぱなしのままS11がON次いでS11がOFFになって代わりにS10がONになるのはまあいいとして、S10がONになったとたんにCLEARが繰り返しトグルし始めた。なんだこれは。結局このために以降シフトレジスタが意図していた通り動かなくなってしまっている。

ステートマシンに問題有りだな。シミュレーション以前の問題かもしれないので見直すことにしよう。

自分で書いたコードは動くと信じたいよね、しかしそうはいかないのが世の常。

webadm
投稿日時: 2008-2-8 12:47
Webmaster
登録日: 2004-11-7
居住地:
投稿: 3095
検証開始
一応論理合成とPlace & Routeが出来たので、動かすことは出来るがいきなり実機でやることは普通しない。

一発で動けば良いが、ここまで来るまでの間にもいろいろ仕様検討時のミスが発見されているので、他にも潜んでいる可能性は大である。実機でやって意図した通り動かなければやはり時間の無駄である。

普通は次ぎの段階としてシミュレーションテストを行うためにテストベンチモジュールを作成することになる。

テストベンチモジュールは今回出来たシグネチャアナライザモジュールを下位モジュールとして入力信号を与えて出力信号を検査するシミュレーション用のトップモジュールである。

以前に1万年カレンダー時計をやった時はこれが面倒でテスト波形を入力してやっていた。

実はQuartusにはtest bench template writerという機能があることに今更ながら知って、それを使わない手はないと思った。

ProcessingのStartメニューでTest Bench Template Writerというのを選択すると自動的に現在のデザインのトップモジュールを駆動するためのテストベンチモジュールのひな形を生成してくれる。

あとはテストケースに応じた信号を駆動するための肉付けをすれば良いということになる。

いやはや至れり尽くせりである。

ソフトウェア開発ツールにもこういうのがないものかのう。

satop.vt:テストベンチトップモジュール(自動生成)

// Copyright (C) 1991-2007 Altera Corporation
// Your use of Altera Corporation's design tools, logic functions
// and other software and tools, and its AMPP partner logic
// functions, and any output files from any of the foregoing
// (including device programming or simulation files), and any
// associated documentation or information are expressly subject
// to the terms and conditions of the Altera Program License
// Subscription Agreement, Altera MegaCore Function License
// Agreement, or other applicable license agreement, including,
// without limitation, that your use is for the sole purpose of
// programming logic devices manufactured by Altera and sold by
// Altera or its authorized distributors. Please refer to the
// applicable agreement for further details.

// *****************************************************************************
// This file contains a Verilog test bench template that is freely editable to
// suit user's needs .Comments are provided in each section to help the user
// fill out necessary details.
// *****************************************************************************
// Generated on "02/08/2008 03:41:48"

// Verilog Test Bench template for design : satop
//
// Simulation tool : ModelSim-Altera (Verilog)
//

`timescale 1 ps/ 1 ps
module satop_vlg_tst();
// constants
// general purpose registers
reg eachvec;
// test vector input registers
reg clk;
reg clock_pol;
reg hold;
reg reset;
reg sa_clock;
reg sa_data;
reg sa_start;
reg sa_stop;
reg start_pol;
reg stop_pol;
// wires
wire [3:0] led_com;
wire led_data;
wire led_gate;
wire [6:0] led_seg;
wire led_unstable;
wire test_clock;
wire test_data;
wire test_start;
wire test_stop;

// assign statements (if any)
satop i1 (
// port map - connection between master ports and signals/registers
.clk(clk),
.clock_pol(clock_pol),
.hold(hold),
.led_com(led_com),
.led_data(led_data),
.led_gate(led_gate),
.led_seg(led_seg),
.led_unstable(led_unstable),
.reset(reset),
.sa_clock(sa_clock),
.sa_data(sa_data),
.sa_start(sa_start),
.sa_stop(sa_stop),
.start_pol(start_pol),
.stop_pol(stop_pol),
.test_clock(test_clock),
.test_data(test_data),
.test_start(test_start),
.test_stop(test_stop)
);
initial
begin
// code that executes only once
// insert code here --> begin

// --> end
$display("Running testbench");
end
always
// optional sensitivity list
// @(event1 or event2 or .... eventn)
begin
// code executes for every event on sensitivity list
// insert code here --> begin

@eachvec;
// --> end
end
endmodule

webadm
投稿日時: 2008-2-8 12:34
Webmaster
登録日: 2004-11-7
居住地:
投稿: 3095
スキャン&テストオシレータの実装
最後がローカルクロック信号生成回路。

外部から基準クロックを供給してもらってそれをバイナリカウンタで分周し、必要な周期のクロックや制御信号をタップ出力する。

一部はテスト信号生成用ROMのアドレスやテストクロックやテストデータとして使用。今回はとりあずSTART/STOPのパルスが出るだけとした。

stosc.v:スキャン&テストオシレータモジュール(実装済み)

module stosc(clk, dcount, dclock, test_clock, test_start, test_stop, test_data);

input clk;

output [3:0] dcount;
output dclock, test_clock, test_start, test_stop, test_data;

reg [9:0] count;

assign dcount = count[3:0];
assign dclock = count[4];
assign test_clock = count[1];
assign test_data = count[2];
assign {test_stop,test_start}=testrom(count[9:5]);

always @ (posedge clk)
begin
count <= count + 1;
end

function [1:0] testrom(input [4:0] addr);
case(addr)
5'b00000: testrom = 2'b11;
default: testrom = 2'b00;
endcase
endfunction

endmodule

RTL Viewerでみるとやはり予想通り。



これで全部のモジュールを実装したのですべての入力信号と出力信号がつながったことになる。当初から予想していた通り、以前にやった1万年カレンダーに比べればはるかに小規模な回路なので使用するLE数も91/240と少ない。これなら古いFLEX8000とかにも収まりそうである。MAXIIとかではもったいないかもしれない。
webadm
投稿日時: 2008-2-8 11:54
Webmaster
登録日: 2004-11-7
居住地:
投稿: 3095
データラッチの実装
次ぎは簡単なデータラッチモジュール。

唯一ややこしいのがデータが変化していることを表示するためのLED_DATA信号の生成パス。

SRFFを仕様では想定していたが、ベンダー固有のプリミティブはなるべく使いたくないのでベンダー非依存な記述を行った。RESETが最も優先順位が高く、次いでデータの変化、最後に更新クロックとしてみた。

dl.v:データラッチモジュール(実装済み)

module dl(sa_data, clock, reset, dclock, data, led_data);

input sa_data, clock, reset, dclock;

output reg data, led_data;

wire data_changed = (sa_data != data);

always @ (negedge reset or posedge clock)
begin
// Reset whenever the reset signal goes low, regardless of the clock
if (!reset)
begin
data <= 1'b0;
end
// If not resetting, update the register output on the clock's rising edge
else
begin
data <= sa_data;
end
end

always @(posedge data_changed or posedge dclock or negedge reset)
begin
// The reset signal overrides the hold signal; reset the value to 0
if (!reset)
begin
led_data <= 1'b0;
end
else if (data_changed)
begin
led_data <= 1'b1;
end
// Otherwise, change the variable only when updates are enabled
else if (dclock)
begin
led_data <= 1'b0;
end
end
endmodule

RTL Viewerで見るとSRFFは生成されずにプリセット付きのDFFとなっていた。なるほど賢い。これでまったく問題ない。


webadm
投稿日時: 2008-2-8 11:30
Webmaster
登録日: 2004-11-7
居住地:
投稿: 3095
表示コントローラーの実装
次ぎは少し面倒くさい表示コントローラー。

最後に生成された疑似乱数を4桁の7セグメントLEDにダイナミック表示するのとあわせて疑似乱数が変動している場合にUNSTABLE LEDを点灯させる。

これは以前にやった1万年カレンダー時計から拝借。基本的にデコーダー回路をVerilogのfunctionで記述している。直接手続き構文中でデコードすると桁毎にデコード回路が生成されてその出力を最後にセレクトするというとんでも無い回路になったのでこのようにした記憶がある。

あとは前回の疑似乱数を保持するレジスタと、UNSTABLE出力を保持するレジスタを追加。

dc.v:表示コントローラー(実装済み)

module dc(prn, dcount, led_seg, led_com, led_unstable);

input [15:0] prn;
input [3:0] dcount;

output [6:0] led_seg;
output [3:0] led_com;
output reg led_unstable;

wire strobe_prn;
wire strobe_unstable;
reg [15:0] prev_prn;

assign strobe_prn = (dcount[1:0] == 2'b00);
assign strobe_unstable = (dcount[1:0] == 2'b10);
assign led_seg = decoder(prnsel(prn, dcount[3:2]));
assign led_com = two2four(dcount[3:2]);

always @ (posedge strobe_prn)
begin
prev_prn <= prn;
end

always @ (posedge strobe_unstable)
begin
led_unstable <= (prev_prn != prn);
end

function [6:0] decoder(input [3:0] seg);
case(seg)
0: decoder = 7'b1000000; // 0
1: decoder = 7'b1111001; // 1
2: decoder = 7'b0100100; // 2
3: decoder = 7'b0110000; // 3
4: decoder = 7'b0011001; // 4
5: decoder = 7'b0010010; // 5
6: decoder = 7'b0000010; // 6
7: decoder = 7'b1111000; // 7
8: decoder = 7'b0000000; // 8
9: decoder = 7'b0010000; // 9
10: decoder = 7'b0001000; // A
11: decoder = 7'b1000110; // C
12: decoder = 7'b0001110; // F
13: decoder = 7'b0001001; // H
14: decoder = 7'b0001100; // P
15: decoder = 7'b1000001; // U
endcase
endfunction

function [3:0] prnsel(input [15:0] prn, input [1:0] sel);
case(sel)
0: prnsel = prn[15:12];
1: prnsel = prn[11:8];
2: prnsel = prn[7:4];
3: prnsel = prn[3:0];
endcase
endfunction

function [3:0] two2four(input [1:0] sel);
case(sel)
0: two2four = 4'b0001;
1: two2four = 4'b0010;
2: two2four = 4'b0100;
3: two2four = 4'b1000;
endcase
endfunction

endmodule

以前の1万年カレンダー時計の記述を見た時点で、制御すべきLEDのセグメント数が7つあるのに、信号が6本しか用意してなかったことに気づく。大失敗。何故6本になったかというと、確か7セグメントLEDには小数点のセグメントがあって、これは要らないからということでひとつ減らして6にしたというバカな間違いを犯していたためである。仕様を直さないと。

合成されたネットリストをRTL Viewerで見ると。



レジスタ周辺は予想通り。表示デコーダーが予想していたのとちょっと見た目が違うけど機能的には等価。

webadm
投稿日時: 2008-2-8 10:06
Webmaster
登録日: 2004-11-7
居住地:
投稿: 3095
疑似乱数生成器の実装
次ぎにややこしい疑似乱数生成器。

これもシフトレジスタの記述はテンプレートから拝借。フィードバック回路とパリティジェネレータ回路にリセットロジックを肉付けし、出力段に出力レジスタを設けてお終い。

prg.v:疑似乱数生成モジュール(実装済み)

module prg(clear, shift, data, reset, prn);

input clear, shift, data, reset;

output reg [15:0] prn;

// Declare the shift register
reg [15:0] sr;

// Shift everything over, load the incoming bit
always @ (posedge shift or negedge clear or negedge reset)
begin
if (!clear | !reset)
begin
sr <= 0;
end
else
begin
sr[15:1] <= sr[14:0];
sr[0] <= data ^ sr[6] ^ sr[11] ^ sr[12] ^ sr[15];
end
end

always @ (negedge clear or negedge reset)
begin
if (!reset)
begin
prn <= 0;
end
else
begin
prn <= sr;
end
end

endmodule

最初に入力した時に出力レジスタをリセットする回路を忘れてしまっていた。RTL Viewerで確認したらシフトレジスタをRESETがアサートされた時にリセットしないと次ぎの計測結果が正しくなくなる仕様上の不備を発見。さっそく仕様にフィードバックしてRESETでどちらのレジスタもリセットされるようにした。自分で決めた仕様の誤りはなかなか自分では気づかない。いわば盲点である。RTL Viewerはその点機械だから正直にそのまま示してくれる。人間は機械のように常に厳しく目を光らせるということはできない。



これも仕様レベルとほぼ一致する。
« 1 2 (3) 4 »
スレッド表示 | 古いものから 前のトピック | 次のトピック | トップ

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