Verilog学習記(3):Verilogデジタル論理回路設計法

1. Verilog言語の設計思想と合成可能な機能

例: Verilog を使用したモジュロ 256 (8 ビット) カウンタの設計

(a) 合成可能なプログラムの記述方法

ここに画像の説明を挿入

(b) エラーを説明する一般的な方法

ここに画像の説明を挿入

同時に、Verilogにはさまざまな回路記述方法があり、回路設計の多様性も決まります。
例: Verilog を使用したデジタル マルチプレクサの設計
(a) 真理値表形式のコード

ここに画像の説明を挿入

(b) 論理式形式のコード
ここに画像の説明を挿入
(c) 構造記述形式のコード

ここに画像の説明を挿入

2. Verilog組み合わせ論理回路

組み合わせ回路の特徴は、回路内の任意の時点の定常状態の出力がその時の入力にのみ依存し、回路の元の状態とは何の関係もないことです。
組み合わせ回路の設計では、次の点を考慮する必要があります。

  • 使用する論理デバイスの数が最も少なく、デバイスの種類も最も少なく、デバイス間の接続が最もシンプルです。このような回路は「最小化」回路と呼ばれます。
  • 第二に、速度要求を満たすためには、段数をできるだけ少なくしてゲート回路の遅延を少なくし、回路の消費電力をできるだけ小さくし、動作が安定して確実であることが必要です。

組み合わせ論理回路を記述するには、構造記述、論理代数、真理値表、抽象記述の 4 つの方法があります。

例: 3 人の審判用の投票回路を設計します。2 人以上の審判が同意した場合、審判は「1」を出力し、そうでない場合は「0」を出力します。
方法 1: 真理値表による方法
真理値表は、回路の機能を記述する最も直接的かつ簡単な方法です。回路の機能に応じて、出力と入力の間の論理関係は真理値表を通じて直接確立できます。この例には 3 つの入力 A、B、C と 1 つの出力 OUT があります。

B C
0 0 0 0
0 0 1 0
0 1 0 0
1 0 0 0
0 1 1 1
1 0 1 1
1 1 0 1
1 1 1 1

Verilog では、「case」ステートメントを使用して回路を記述的に設計できます。上の表に従って設計します。
ここに画像の説明を挿入
ここに画像の説明を挿入
方法 2: 論理代数
組み合わせ回路のもう 1 つの表現方法は、論理代数方法です。主なアイデアは、真理値表をカルノー図で表現し、回路を単純化して論理関数の式を取得することです。
カルノー図の単純化により、組み合わせ回路の論理出力と入力間の論理関数式が得られます。
ここに画像の説明を挿入
論理関数式に従って、論理代数記述法を使用して Verilog を記述すると非常に便利です。

module desingn(OUT,A,B,C);
output OUT;
input A,B,C;

assign OUT = (A&B) | (B&C) | (A&C);

endmodule

方法 3: 構造記述方法
構造記述方法は回路を最も直接的に表現する方法であり、初期のデジタル回路設計で通常使用される回路図設計は実際には構造記述方法です。

module desingn(OUT,A,B,C):
output OUT;
input A,B,C;

and U1(w1,A,B);
and U2(w2,B,C);
and U3(w3,A,C);
or U4(OUT,w1,w2,w3);

endmodule

ここに画像の説明を挿入
手法 4: 抽象記述手法
Verilog では、回路機能から直接コードを記述できる抽象記述を使用した回路設計手法も提供しています。たとえば、決定装置の設計では、3 つの入力の判定が加算され、判定が成功すると加算器の合計が 1 より大きくなり、投票が成功したことになります。

module  desingn(OUT,A,B,C);
output OUT;
input A,B,C;
wire [1:0} sum;
reg OUT;

assign sum = A + B + C;
always@(sum)
	if(sum > 1)
		OUT = 1;
	else
		OUT = 0;
endmodule

2.1 デジタル加算器

デジタル加算器は、コンピュータ、通信、マルチメディアデジタル集積回路で広く使用されている最も一般的に使用されるデジタル演算ロジックです (
例: 2 入力 1 ビット信号全加算器)。下位ビットからの桁上がりを考えるとこの演算は全加算演算となり、全加算演算を実現する回路を全加算器と呼びます。
ここに画像の説明を挿入
代数論理は次
ここに画像の説明を挿入
のように表現されます。 対応する回路は次のとおりです。
ここに画像の説明を挿入
Verilog は 1 ビット全加算器をさまざまな記述方法で記述することができ、集積回路は同じですが、記述形式が異なります。
(1) 連続代入文で実現

module one_bit_fulladder(SUM, C_OUT, A, B, C_IN);
input A, B, C_IN;
output Sum, C_OUT;
	assign SUM = (A ^ B) ^ C_IN;
	assign C_OUT = (A & B) | ((A ^ B) & C_IN);
endmodule

(2) 動作記述を用いて実現する

module one_bit_fulladder(SUM, C_OUT, A, B, C_IN);
input A, B, C_IN;
output SUM, C_OUT;
	assign {C_OUT,SUM} = A + B + C_IN;
endmodule

動作記述を使用すると、設計効率が向上します。一般的な多ビット加算器の動作記述設計では、コード内で入出力信号のビット幅を変更するだけで済みます。たとえば、2入力8ビット加算器です。 : 例: 4 ビット
ここに画像の説明を挿入
スーパーキャリーフォワード加算器
キャリーフォワード加算器は高速加算器です. キャリーの各段は追加の組み合わせ回路によって生成されます. 上位演算は桁上げの完了を待つ必要がありません低次演算が可能なため、演算速度の向上が可能です。
入力信号ビット幅が N の全加算器によると、そのキャリー信号は次のようになります。
ある
出力加算結果は次のようになります。

ここに画像の説明を挿入
アドバンスト キャリー フラグ信号は です。
ここに画像の説明を挿入
キャリー生成関数は です。
ここに画像の説明を挿入
キャリー転送関数は です
ここに画像の説明を挿入
。 上式において、N は加算器の数であり、4 ビット加算器では N=4 となります。この式から、すべてのレベルのキャリー信号の式を推定することができ、高速なキャリー論理回路を構成できます。
ここに画像の説明を挿入
4 ビット桁上げ加算器の回路図は次のとおりです
ここに画像の説明を挿入
。 4 ビット桁上げ加算器の Verilog コード:
ここに画像の説明を挿入

2.2 データコンパレータ

データコンパレータは、2 つの 2 進数の大小を比較したり、それらが等しいかどうかを検出するために使用される論理回路です。データ コンパレータは 2 つの部分で構成されており、1 つは 2 つの数値の大きさを比較するもので、もう 1 つは 2 つの数値が一致しているかどうかを検出するものです。
例:4 ビット数値比較器
多桁数値比較器の比較処理は、上位ビットと下位ビットを 1 つずつ比較し、上位ビットが等しい場合のみ下位ビットを比較します。4 ビット数値比較器でA 3 A 2 A 1 A 0と B 3 B 2 B 1 B 0を比較する場合、最上位ビット A 3と B 3を最初に比較する必要があります。A 3 >B 3の場合、他の数字が何であっても、結果は A>B となり、A 3 <B 3の場合、A< B になります。=B3の場合、下位ビットA とBを比較してAとBの大きさを判断する必要がある。A 2 =B 2の場合、A 1の下位ビットもB と比較する必要があります。1比較の最後のビットまで判断します。完全に等しい場合は、前段の結果 C (カスケード入力) によって決まります。
ここに画像の説明を挿入

module four_bits_comp(F, A, B,C);
parameter comp_width = 4;
output [2:0] F;
input [comp_width-1:0] A;
input [comp_width-1:0] B;
ref [2:0] F;
always@(A or B or C)
	if(A>B)
		F = 3'b100;
	else if(A<B)
		F = 3'b001;
	else
		F = C;
endmodule

2.3 データセレクター

データ セレクターはマルチプレクサー (略して MUX) とも呼ばれ、n ビットのアドレス入力、2 つのnビット データ入力、および 1 ビットのデータ出力を備えています。入力アドレスの制御下で毎回、複数の入力データから 1 つの出力が選択され、その機能は図に示すように単極多投スイッチに似ています。たとえば、8 対 1 データ セレクターです
ここに画像の説明を挿入

8:1 データ セレクターは、複数の 2:1 セレクター構成で構成できます。
ここに画像の説明を挿入
(1) 複数の 2:1 データ セレクターの構造レベルの記述

module mux8to1(d_out, d_in, sel); 
output	d_out;
input[7:0] d_in;
input [2:0] sel;
wire[3:0] w1;
wire[1:0] w2;
	assign w1 = sel[0] ? {d_in[7], d_in[5], d_in[3], d_in[1]} : {d_in[6], d_in[4], d_in[2], d_in[0]};
	assign w2 = sel[1] ? {w1[3], w1[1]} : {w1[2], w1[0]};
	assign d_out = sel[2] ? w2[1] : w2[0];
endmodule

(2) 抽象記述方法
マルチプレクサの設計は、case 文により設計することができます。
ここに画像の説明を挿入

2.4 デジタルエンコーダ

特定のオブジェクトを単語、記号、または数字で表すプロセスはコーディングと呼ばれます。デジタル回路において、関連する信号をバイナリコードで表現することをバイナリコーディングといいます。この符号化動作を実現する回路をエンコーダと呼びます。
例:3ビットバイナリ8-3線式エンコーダN=2 n 個
の一般信号をnビットのバイナリコードでエンコードする回路をバイナリエンコーダといいます。例えば、n=3、8個の一般的な信号を符号化することができる。このエンコーダは、一度に入力できる有効信号は 1 つだけであり、同時に 2 つ以上の有効信号を入力できないという特徴があります。次のブロック図:真理値表:


ここに画像の説明を挿入

ここに画像の説明を挿入

module 8to3(F, I);
output [2:0] F;
input [7:0} I;
reg [2:0] F;
always@(I)
	case(I):
		8'b00000001:F=3'b000;
		8'b00000010:F=3'b001;
		8'b00000100:F=3'b010;
		8'b00001000:F=3'b011;
		8'b00010000:F=3'b100;
		8'b00100000:F=3'b101;
		8'b01000000:F=3'b110;
		8'b10000000:F=3'b111;
		 default: F= 3'bx;
	endcase
endmodule

例: 8 線 3 線のプライオリティ エンコーダ
バイナリ エンコーダ回路では、常に 1 つの入力のみが有効である必要があります。2 つ以上の入力信号が同時に有効な場合、出力の混乱が生じるため、特定の制限があります。使用プロセスセックス。入力信号の要件を克服するための 1 つのアプローチは、プライオリティ エンコーダを使用することです。プライオリティエンコーダは複数の入力信号を同時に有効にしますが、その中で最も優先度の高い有効な入力信号のみをエンコードし、レベルの低い入力信号は無視します。
機能表:
ここに画像の説明を挿入
ここに画像の説明を挿入
ここに画像の説明を挿入
ここに画像の説明を挿入
例:バイナリ変換10進数8421 BCDエンコーダ
10進数0、1、2、3、4、5、6、7、8、9など10個の信号をバイナリコードにエンコードする回路をバイナリ変換10進数エンコーダといいます。 。入力は 0 ~ 9 の 10 個の数字を表す状態情報で、有効な信号は 1 (つまり、特定の信号が 1 の場合、エンコードする必要があることを意味します)、出力は対応する BCD コードです。そのため、10 線 1 4 線式エンコーダとも呼ばれます。バイナリエンコーダと同じ特性を持ち、一度に有効な信号を 1 つだけ入力できます。
ここに画像の説明を挿入
ここに画像の説明を挿入
例: 8421BCD 10 進剰余 3 エンコーダは
8421BCD コードと同じです。剰余 3 コードも BCD コードの一種です。このエンコードの特徴は、剰余 3 コードを 10 進加算に使用する場合、 2 つの数値が 10 で、2 進数の 16 に正確に等しい場合、キャリー信号は上位ビットから自動的に生成されるため、残りの 3 つのコードを使用できます。
残り3ヤードのコード表:
ここに画像の説明を挿入ここに画像の説明を挿入

2.5 デジタルデコーダ

デコードはエンコードの逆のプロセスであり、バイナリ コードで表される情報を対応する状態情報に変換します。デコード機能を実現する回路がデコーダとなります。
図は2-4線式デコーダの論理回路と論理記号を示しています。図中、A1A0アドレス入力端子であり、A1上位ビットである。非Y0 非Y3ステータス信号出力端子で、「非」はローポイントがアクティブであることを意味します。E はイネーブル端子 (またはゲート制御端子) であり、ローレベルでアクティブになります。E = 0 の場合、デコーダの動作が許可され、非 Y 0~ 非 Y 3の 1 つだけがアクティブ レベル出力になることが許可されます。E = 1 の場合、デコーダの動作が禁止され、すべての出力がアクティブになります。高い。
一般にイネーブル端子の目的は、ストローブパルスを導入して危険パルスの発生を抑制することと、入力変数の数を拡張すること(機能拡張)の2つがあります。ここに画像の説明を挿入
ここに画像の説明を挿入
ここに画像の説明を挿入
ここに画像の説明を挿入

2.6 パリティチェッカー

パリティチェッカーの機能は、データ内の「1」の数が奇数か偶数かを検出することです。コンピュータや一部のデジタル通信システムでは、データ送信やデジタル記録のエラーをチェックするためにパリティ チェッカーが一般的に使用されます。
パリティには奇数と偶数の 2 種類があります。奇数パリティは、送信されるデータ ビットとパリティ ビットの「1」の合計数が奇数であることを保証します。データに奇数の「1」が含まれる場合、チェック位置は「0」、データに偶数の「1」が含まれる場合、チェック位置は「1」になります。偶数パリティでは、送信されるデータ ビットとパリティ ビットの「1」の合計数が偶数であることが保証されます。データに奇数の「1」が含まれている場合は「1」の位置を確認し、データに偶数の「1」が含まれている場合は「0」の位置を確認します。
パリティ チェックは一部の送信エラーのみを検出でき、どのビットでエラーが発生したかを判断できないため、エラー訂正は実行できません。データの再送信はデータにエラーが発生した場合のみ可能です。
例: 8 ビット パリティ チェッカ
8 ビット パリティ チェッカの概略図を図に示します。図では、
ここに画像の説明を挿入
チェッカの入力 b 0~ b 7は 7 ビットのデータと 1 ビットのチェック ビットで構成されます。F ODは奇数出力、F EVは偶数出力です。奇数パリティを使用する場合、F OD = 1、F EV = 0、偶数パリティを使用する場合、F OD =0、F EV = 1。
ここに画像の説明を挿入
ここに画像の説明を挿入

3. 順序回路

組み合わせ論理回路とは異なり、順序論理回路の出力は、現時点での入力変数の値だけでなく、回路の元の状態、つまり過去の入力条件にも関係します。

ここに画像の説明を挿入
順序論理回路には 2 つの特徴があります:
(1) 順序論理回路は組み合わせ論理回路と記憶回路の 2 つの部分から構成され、記憶回路はメモリ機能を持ち、通常はフリップフロップで構成されます (2) 記憶回路の状態
は組み合わせ論理回路の入力端子にフィードバックされ、外部入力信号とともに組み合わせ論理回路の出力を決定します。
同期順序回路の設計プロセス:
ここに画像の説明を挿入
例: Verilog を使用して「111」シーケンス検出器を設計します。「1」が 3 つ以上入力されると回路出力は 1、それ以外の場合は 0 になります。
(1) 状態遷移図法
ここに画像の説明を挿入
S 0 : 回路がまだ有効な 1 を受け取っていないことを示す初期状態。
S 1 : 回路が 1 を受信したことを示します。
S 2 : 回路が 2 つの連続した 1 を受信したことを示します。
S 3 : 回路が 3 回連続した 1 を受信したことを示します。

回路図:
ここに画像の説明を挿入

module check(z, x, clk);
parameter s0 = 2'b00, s1 = 2'b01, s2 = 2'b10, s3 = 2'b11;
output z;
input x, clk;
reg[1:0} state, next_state;
reg z;
always@(posedge clk)
case(state)
	s0:if(x)
			begin
				next_state <= s1;
				z = 0;
			end
		else
			begin
				next_state <= s0;
				z = 0;
			end
	s1:if(x)
			begin
				next_state <= s2;
				z = 0;
			end
		else
			begin
				next_state <= s0;
				z = 0;
			end	
	s2:if(x)
			begin
				next_state <= s3;
				z = 1;
			end
		else
			begin
				next_state <= s0;
				z = 0;
			end	
	s0:if(x)
			begin
				next_state <= s3;
				z = 0;
			end
		else
			begin
				next_state <= s0;
				z = 0;
			end
endcase
always@(posedge clk)
	state <= next_state;
endmodule

(2) 状態の簡略化に基づく構造記述法
状態遷移図を簡略化するには、残りの状態は 3 つだけであり、2 ビットのバイナリ表現が必要です。つまり、状態を保存するには 2 つの D フリップフロップが必要です。Q 1が高位レジスタの出力を表し、Q 0が低位レジスタの出力を表すものとします。状態ジャンプと出力 Z は、次のようにカルノー図の形で示されます。ここに画像の説明を挿入回路の出力方程式と状態方程式は、カルノー図から取得できます。
Q 1 n+1 = Q 1
Q 0 n+1 = X
Z = Q 1 Q 0 X

//D触发器模块
module DFF(Q, D, clk);
output Q;
input D, clk;
reg Q;
always@(posedge clk)
	Q <= D;
endmodule

//序列检测模块
module check(z, x, clk);
output z;
input x,clk;
wire w1,w2;
DFF U1(.clk(clk), .D(x), .Q(w1));
DFF U2(.clk(clk), .D(w1), .Q(w2));
assign z = x&w1&w2;
endmodule

ここに画像の説明を挿入
(3) Verilog HDL の抽象記述方法
Verilog では回路を抽象的に記述することもできます。シーケンス「111」の検出を実現するには、3 ビットのシフト レジスタを使用し、出力 x をシフト レジスタの出力として使用し、レジスタが 111 のとき、出力 Z は 1 になります。

module check(z, x, clk);
output z;
input x,clk;
reg[2:0] q;
reg z;
always@(posedge clk) 
	q <= {q[1:0], x};
always@(posedge clk)
	if(q == 3'b111)
		z = 1;
	else
		z = 0;
endmodule

ここに画像の説明を挿入

3.1 トリガー

フリップフロップは順序回路の最も基本的な回路単位であり、主にDフリップフロップ、JKフリップフロップ、Tフリップフロップ、RSフリップフロップが含まれます。さまざまな機能要件に応じて、フリップフロップにはセット、リセット、イネーブル、選択などの機能もあります。

3.1.1 単純な D フリップフロップ

ここに画像の説明を挿入

カチカチ D Qn _ Qn +1
0 バツ 0 0
0 バツ 1 1
1 バツ 0 0
1 バツ 1 1
0 0 0
0 1 0
1 0 1
1 1 1
module DFF(Q, D, clk);
output Q;
input D, clk;
reg Q;
always@(posedge clk)
	Q <= D;
endmodule

入力端のデータDはクロックclkの立ち上がりエッジでフリップフロップに送られるので、Q=Dとなる。その特性方程式は、Q n+1 = D nとして記述できます

3.1.2 リセット端子 (クリア端子) 付き D フリップフロップ:

ここに画像の説明を挿入
同期クリアトリガー:

module DFF_rst(q, clk, rst_n, d);
output q;
input clk,rst_n,d;
reg q;
always@(posedge clk)
	if(!rst_n)
		q<=0;
	else
		q<=d;
endmodule

トリガーは非同期でクリアされました:

module DFF_rst(q, clk, rst_n, d);
output q;
input clk,srst_n,d;
reg q;
always@(posedge clk or rst_n)
	if(!rst_n)
		q<=0;
	else
		q<=d;
endmodule

3.1.3 複素関数 D フリップフロップ

同期クリア 0、セット 1 と非同期クリア 0、セット 1 の複素 D フリップフロップを 1 つのフリップフロップにまとめています。

module DFF(q, qb, clk, rst_n1, set1, rst_n2, set2, data_in); 
output q, qb;
input clk, rst_n1,rst_n2, set1,set2, data_in;
reg q,qb;
always@(posedge clk)
	if(!rst_n1) 
		q<=0;
	else 
		q<=data_in;
always@(posedge clk or rst_n2) 
	if(!rst_n2) 
		q<=0;
	else 
		q<=data_in;
endmodule

3.1.4 T フリップフロップ

T フリップフロップの論理記号は次のとおりです T フリップフロップの機能: クロックの有効エッジが到着すると、T=1 の場合はフリップフロップが反転し、T=0 の場合はフリップフロップの状態が反転します。フリップフロップは変更されません。R はリセット端子、非同期リセット、アクティブ ローです。
ここに画像の説明を挿入

module TFF(d, t, clk, rst_n);
output d;
input t, clk, rst_n;
reg d;
always@(posedge clk or rst_n)
	if(!rst_n)
		d <= 1'b0;
	else if(t)
		d <= ~d;
endmodule

3.2 カウンタ

3.2.1 バイナリカウンタ

ここに画像の説明を挿入

module comp2(q, clk, rst);
output q;
input clk,rst;
reg q;
always@(posedge clk or rst_n)
 if(!rst)
 	q <= 1'b0;
 else
  q <= ~q;
endmodule

3.2.2 任意の係数によるカウンター

モジュラス値 M を持つカウンタの場合、最初のステップは、カウンタに必要なフリップフロップの数を決定することです。N 個のフリップフロップは 2 N 個の状態に対応します。条件を満たす最小の N を選択するには、 2 N > M 個の任意のモジュラス カウンタが必要です。N はカウンタ内のフリップフロップの数です。実現方法としては、フィードバックのクリア方法とフィードバックの設定方法の2つがあります。

//反馈清零法设计的模11计数器
module comp11(count, clk, rst);
output[3:0] count;
input clk,rst;
reg[3:0] count;
always@(posedge clk)
if(rst)
	count <= 4'b0000;
else
	if(count == 4'b1010)
		count <= 4'b0000;
	else
	 count <= count + 1;
endmodule

3.3 シフトレジスタ

シフトレジスタはデータのシリアル/パラレル変換を実現したり、カウントや分周を行うシフトラインカウンタを構成したり、シーケンスコード発生器やシーケンスコード検出器などを構成したりすることができ、広く使用されています。デジタル システムで使用される順序論理コンポーネントの 1 つ。
例: リング シフト レジスタ
N ビット リング レジスタは N 個のシフト レジスタで構成され、リング シフトを実現できます。

ここに画像の説明を挿入
各レジスタの出力を次のビット レジスタへの入力として使用し、上位ビット レジスタの出力をループへの入力として使用します。

module shiftregist(D, clk, rst_n);
parameter shiftregist_width = 4;
output [shiftregist_width-1:0] D;
input clk,rst_n;
reg [shiftregist_width-1:0] D;

always@(posedge clk)
	if(!rst_n)
		D<=4'b0000;
	else
		D<={D[shiftregist_width-2:0], D[shiftregist_width-2:1]};
endmodule

3.4 シーケンス信号発生器

シーケンス信号はデジタル回路システムで一般的に使用される機能単位であり、シーケンスサイクル長 M とフリップフロップ数 n の関係により、一般に次の 3 種類に分類できます: (1) 最大サイクル長シーケンスコード
、 M=2 n ;
(2) 最長ライン形状系列符号 (m 系列符号)、M=2 n -1;
(3) 任意の巡回長系列符号、M<2 n
シーケンス信号発生器は、1 つ以上のシーケンス信号を生成できる順序回路であり、純粋な順序回路、または順序論理と組み合わせ論理を含むハイブリッド回路で構成できます。
例: 10011 のシーケンスを生成する信号発生器を設計する

  • 方法(1): シフトレジスタで構成する
    シフトレジスタの入力信号と出力信号の間に組み合わせ回路がなく、組み合わせ論理によるフィードバック動作が不要なため、この系列生成回路の動作周波数は非常に高い。欠点は、シフト レジスタの長さがシーケンスの長さに依存するため、回路の大きな面積を占めることです。
    ここに画像の説明を挿入
module maker(out, clk, load, D);
parameter M=6;
output out;
input clk,load;
input [M-1:0] D;
reg [M-1:0] Q;
initial Q=6'b10011;
always@(posedge clk)
	if(load)
		Q<=D;
	else
		Q<={Q[M-2:0], Q[M-1]};
assign out=Q[M];
endmodule


方法 (2):シフト レジスタと組み合わせ論理回路で構成されるフィードバック シフト シーケンス コード生成器の構造ブロック図を図に示します. シフト レジスタと組み合わせ論理ネットワークで構成されます.
ここに画像の説明を挿入
その設計は次の手順に従って実行されます。
(1) 与えられたシーケンス信号のサイクル周期 M に従って、シフト レジスタのビット数 n を決定します (2 n-1 < M ≤ 2 n)
(2) シフト レジスタの M 個の独立した状態を決定します。シフト規則に従って、与えられたシーケンス コードは n ビットごとに M 個の状態に分割されます。M 個の状態で繰り返しが発生する場合は、シフト レジスタのビット数を増やす必要があります。上記のプロセスを n+1 ビットで繰り返し、M 個の独立した状態に分割します。
(3) M 個の異なる状態に従ってシフト レジスタの状態シーケンス テーブルとフィードバック関数テーブルをリストし、フィードバック関数 F の式を求めます。
(4) 自己始動性能を確認してください。
上記のシーケンス信号発生器と比較すると、各レジスタの出力はシフト レジスタの入力に接続される前にフィードバック ネットワークを通過する必要があります。したがって、回路の速度は必然的に低下しますが、フィードバック ネットワークの利点はレジスタを節約できることです。
「1001 1 1」シーケンスの信号発生器。
まず、必要なシフト レジスタの数 n を決定します。M = 6 なので、n は 3 になります。
次に、シフト レジスタの 6 つの独立した状態が決定されます。
法律によれば、3 桁の各グループは 100,001,011,111,111,110 のように 6 つの州に分割されます。状態 111 が繰り返し現れるため、n=4 とし、状態を再分割すると、1001、0011、0111、1111、1110、1100 が得られます。したがって、n=4となる。
第三に、状態系列テーブルとフィードバック励磁関数テーブルを列挙し、フィードバック関数 F の式を求めます。
次の表に示すように、最初に状態シーケンス テーブルをリストし、次に各状態に必要なシフト入力、つまりフィードバック入力信号に応じてフィードバック励磁関数テーブルをリストします。フィードバック活性化関数を見つけます。
ここに画像の説明を挿入
ここに画像の説明を挿入

//反馈移位型序列信号发生器
module maker(out, clk, load, D);
parameter M=4;
output out;
input clk,load;
input [M-1:0] D;
reg {M-1:0] Q;
wire w1;

always@(posedge clk)
	if(load)
		Q<=D;
	else
		Q<={Q[M-2:0],ww1};
	assign w1 = (~Q[3])|((~Q[1])&(~Q[0]))|(Q[3]&(~Q[2]));
	assign out =Q[M-1];
endmodule

方法(3):カウンタで構成する
計数系列信号発生器と帰還系列信号発生器はほぼ同じであり、どちらも順序回路と組み合わせ回路で構成されます。違いは、フィードバック シーケンス信号発生器のタイミング状態はシフト レジスタによって生成され、出力はレジスタの最上位ビットを取るのに対し、カウント型シーケンス信号発生器ではシフト レジスタの代わりにカウンタが使用されて出力されることです。はタイミング状態を生成し、出力は組み合わせ回路によって生成されます。
カウント型の利点は、カウンタの状態設定が出力順序に直接関係せず、上記のように出力に応じて状態を判断する必要がないことです。必要なのは、フィードバック ネットワークを適切に設計することだけです。したがって、計数構造は出力シーケンスを変更するのにより便利であり、異なるフィードバックネットワークに接続されている限り、複数セットのシーケンスコードを同時に生成できます。
ここに画像の説明を挿入
設計プロセスは 2 つのステップに分かれており、
まずシーケンス コードの長さ M に従って状態をカスタマイズできるモジュロ M カウンタを設計し、
次にカウンタと状態の遷移関係に従って結合された出力ネットワークを設計します。シーケンスコードの要件。「100111」シーケンスの信号発生器。モジュロ 6 カウンタを選択する必要があるため、シーケンス信号の M 値は 6 です。カウンタの状態選択は000から101まであり、以下の表が得られます。
ここに画像の説明を挿入
カルノー図は真理値表から描画して出力関数を取得できます。
ここに画像の説明を挿入
次のコードです。

module maker(OUT, clk, reset);
parameter M=3;
input clk,reset;
reg [M-1:0] counter;
always@(posedge clk)
	if(!reset)
		counter <= 3'b000;
	else
		counter <= counter + 1;
	assign OUT = counter[2] | ((~counter[1])&(~counter[0])) | (counter[1]&counter[0]);
endmodule

例: 擬似ランダム コード生成器の設計
ランダム コードは、ランダム コードと同様の変化規則を持つバイナリ コードで、デジタル通信の信号源として使用され、チャネルを通じて受信機に送信され、確率を検出します。デジタル通信システムにおけるエラーコード、つまりビット誤り率。

従来のデジタル回路設計では、擬似ランダムシーケンス信号発生器はシフトストレージカウンターによって実現され、フィードバックネットワークの入力信号はシフトストレージカウンターの出力端子の一部(Q N-1 ~ Q 0 )から取得されます register シフト レジスタのシリアル入力へのフィードバックの出力 F。

さまざまなフィードバック ネットワークを通じて、さまざまな転送タイプのカウンターを形成できます。m 系列コードを例として、フィードバック関数を次の表に示します。表中の N はフリップフロップの数、F はフィードバック関数のリストです。
ここに画像の説明を挿入
たとえば、N = 4 の場合、フィードバック関数は次のようになります。
ここに画像の説明を挿入
N = 4 を例にとると、15 ビット最長の線形シーケンス シフト カウンタには、無限ループを破るために「0000」で構成される無限ループがあります。ループの場合、式は次のように変更できます。
ここに画像の説明を挿入
N=4 の最長線形シーケンスに従ってシフト レジスタ カウンター。

module signal(out, clk, load_n, D_load);
output out;
input load_n,clk;
input [3:0] D_load;
reg [3:0] Q;
wire F;
always@(posedge clk)
	if(~load_n)
		Q<=D_load;
	else
		Q<={Q[2:0],F};
	assign F = (Q[1]^Q[0]) | (~Q[3]&~Q[2]&~Q[1]&~Q[0]);
	assign out = Q[3];
endmodule

4. 有限同期ステートマシン

有限状態マシンは順序回路の一般的なモデルであり、任意の順序回路は有限状態マシンとして表現できます。有限ステートマシンは基本的にレジスタと組み合わせ論理で構成される順序回路であり、状態間の遷移は常にクロックによってトリガされ、状態情報はレジスタに格納されます。状態の数が有限であるため、このメソッドが呼び出されます有限状态机
他の順序回路と同様に、有限状態マシンも記憶回路と組み合わせ論理回路の 2 つの部分で構成されます。記憶回路はステート マシンの状態を生成するために使用され、組み合わせ論理回路はステート マシンがジャンプするための出力と条件を提供するために使用されます。
ここに画像の説明を挿入
出力信号の生成方法に応じて、有限状態マシンは、Mealy タイプと Moore タイプの 2 つのタイプに分類できます。Mealy タイプのステート マシンの出力は現在の状態と入力に関連しますが、Moore タイプのステート マシンの出力は現在の状態にのみ依存し、入力とは何の関係もありません。
ここに画像の説明を挿入
ステート マシンのエンコード方法は多数あり、結果として得られる回路も異なります。一般的なエンコード方法は、バイナリ エンコード、グレイ エンコード、1 ビット ワンホット エンコードの 3 つです。
(1) バイナリコーディング:ステータスレジスタはフリップフロップで構成されます。N 個のフリップフロップは 2 n個の状態を形成できます。バイナリ コーディングの利点は、使用するフリップフロップが少なくリソースが節約できることですが、欠点は、状態がジャンプするときに複数のビットが同時に変化し、グリッチや論理エラーが発生する可能性があることです。
(2) グレイコーディング: グレイコーディングはバイナリコーディングに似ています。グレイコーディング状態がジャンプするときに変化するのは 1 ビットだけなので、グリッチや一部の過渡状態の可能性が減ります。
(3) 1 つのホット エンコーディング: n ビットを使用して n 状態をエンコードし、各状態エンコーディングで 1 ビットだけが 1 になります (0001、0010、0100、1000 など)。ワン ホット エンコードでは使用するフリップフロップの数が増加しますが、このエンコードはデコードに便利で、組み合わせ回路を効果的に節約して簡素化できます。

Verilog では、有限状態マシンを記述する方法が数多くあり、2 段階と 3 段階が一般的に使用されます。
(1) ステートマシンの 2 段階の記述:

//第一个进程,同步时序always模块,格式化描述次态寄存器迁移到现态寄存器
always@(posedge clk or negedge rst_n) //异步复位
	if(!rst_n) 
		current_state <= IDLE; 
	else
		current_state <= next_state; //注意,使用的是非阻塞赋值
	//第二个进程,组合逻辑always模块,描述状态转移条件判断 
always@(current_state) //电平触发 
	begin 
		next state = x; //要初始化,使得系统复位后能进入正确的状态 
		case(current_state)
			S1:if(...)
				next_state=S2; //阻塞赋值 
				out1<= 1'b1;//注意是非阻塞逻辑
				...
		endcase 
	end

(2) ステートマシンの 3 段階の記述:

//第一个进程,同步时序always模块,格式化描述次态寄存器迁移到现态寄存器 
always @ (posedge clk or negedge rst_n) //异步复位 
	if(!rst_n)
		current_state <= IDLE; 
	else
		current_state <= next_state;//注意,使用的是非阻塞赋值
//二个进程,组合逻辑always模块,描述状态转移条件判断 
always @ (current_state) //电平触发 
	begin 
		next_state=x; //要初始化,使得系统复位后能进入正确的状态 
		case(current_state) 
		S1:if(...)
			next_state=S2; //阻塞赋值 
			...
		endcase
	end
//第三个进程,同步时序always模块,格式化描述次态寄存器输出 
always@(posedge clk or negedge rst_n) 
...//初始化
case(next_state)
	S1:
		out1 <= 1'b1;//注意是非阻塞逻辑
	S2:
		out2 <= 1'b1;
	default:... //default的作用是免除综合工具综合出锁存器。
endcase
end
//三段式不一定要写三个always块,如果状态机更为复杂,always块也会相应增加。

例: シーケンシャル パルス ジェネレータの設計
シーケンシャル パルス ジェネレータはパルス ディストリビュータとも呼ばれ、高レベルのパルスを異なる出力に順番に分配します。各クロックで 1 つの出力のみがハイレベルのパルスであることが保証され、異なるクロックのパルス レベルがすべての出力に順番に表示されます。

4 ビットのシーケンシャル パルス ジェネレータを例に挙げると、4 つの出力 W 0 W 1 W 2 W 3があり、ハイレベルのパルスが各出力に順番に表示され、出力サイクルは 1000、0100、0010、0001 の間になります。4ビットシーケンシャルパルス発生器の状態遷移図。図に示すように4つのステートで構成されており、各ステートの「1」の数が1つなので、各クロックサイクルで出力端子の1つだけがハイレベル(パルス)となり、順番に現れることになります。生成された連続パルス信号。
ここに画像の説明を挿入
4 ステート マシンをエンコードする場合、必要なバイナリ エンコードは 2 ビットだけです。

module state4(out, clk);
output [3:0] out;
input clk;
reg [3:0] out;
reg [1:0] state, next_state;
always@(state)
	case(state)
		2'b00:
			begin
				out <= 4'b1000;
				next_state <= 2'b01;
			end
		2'b01:
			begin
				out <= 4'b0100;
				next_state <= 2'b10;
			end
		2'b10:
			begin
				out <= 4'b0010;
				next_state <= 2'b11;
			end
		2'b00:
			begin
				out <= 4'b0001;
				next_state <= 2'b010;
			end
	endcase
always@(posedge clk)
	state <= next_state;
endmodule

例: 新聞の自動販売機を設計します。新聞の価格は 8 セント、紙幣は 1 セント、2 セント、5 セント、1 元です。この新聞販売機は、硬貨の高額額などの特殊な状況を考慮していません。下図は新聞販売機の状態遷移図です図中、S0~S7はステートマシンの8つの状態、添え字は投入されたコインの合計を表します。はコインではなく、S1 は 1 jiao が投資されたことを意味します。M は入力、M1 は 1 角硬貨を入れること、M2 は 2 角硬貨を入れること、M5 は 5 角硬貨を入れること、M10 は 1 元を入れることを表します。
ここに画像の説明を挿入
Verilog コード:

//data_out=1表示给出报纸,data_out_return=1表示找回1角硬币,data_out_return2=1表示找回2角硬币
module auto_sellor(current_state,data_out, data_out_return1, data_out_retum2, clk, rst_n, data_in);
parameter state_width = 3, data_in_width = 3; 
output [state_width-1:0] current_state; 
output data_out, data_out_return1, data_out_return2;
input [data_in_width-1:0] data_in;
input clk, rst_n;
reg [state_width-1 :0] current_state, next_state; 
reg data_out, data_out_return1, data_out_return2; 
always@(current_state or rst_n)
	if (!rstn)
		next_statec=0;
	else
		case(current_state)
			3'b000: 
				case(data_in)
					3'b000: 
						begin
							next_state <= 3'b000; 
							data_out <=1'b0; 
							data_out_return1 <=1'b0; 
							data_out_return2 <= 1'b0; 
						end
					3'b001: 
						begin
							next_state <= 3'b001; 
							data_out <=1'b0; 
							data_out_return1 <=1'b0; 
							data_out_return2 <= 1'b0; 
						end
					3'b010: 
						begin
							next_state <= 3'b010; 
							data_out <=1'b0; 
							data_out_return1 <=1'b0; 
							data_out_return2 <= 1'b0; 
						end
					3'b011: 
						begin
							next_state <= 3'b101; 
							data_out <=1'b0; 
							data_out_return1 <=1'b0; 
							data_out_return2 <= 1'b0; 
						end
					3'b100: 
						begin
							next_state <= 3'b000; 
							data_out <=1'b1; 
							data_out_return1 <=1'b0; 
							data_out_return2 <= 1'b1; 
						end
				endcase
			3'b001: 
				case(data_in)
					3'b000: 
						begin
							next_state <= 3'b001; 
							data_out <=1'b0; 
							data_out_return1 <=1'b0; 
							data_out_return2 <= 1'b0; 
						end
					3'b001: 
						begin
							next_state <= 3'b010; 
							data_out <=1'b0; 
							data_out_return1 <=1'b0; 
							data_out_return2 <= 1'b0; 
						end
					3'b010: 
						begin
							next_state <= 3'b011; 
							data_out <=1'b0; 
							data_out_return1 <=1'b0; 
							data_out_return2 <= 1'b0; 
						end
					3'b011: 
						begin
							next_state <= 3'b110; 
							data_out <=1'b0; 
							data_out_return1 <=1'b0; 
							data_out_return2 <= 1'b0; 
						end
				endcase
			3'b010: 
				case(data_in)
					3'b000: 
						begin
							next_state <= 3'b010; 
							data_out <=1'b0; 
							data_out_return1 <=1'b0; 
							data_out_return2 <= 1'b0; 
						end
					3'b001: 
						begin
							next_state <= 3'b011; 
							data_out <=1'b0; 
							data_out_return1 <=1'b0; 
							data_out_return2 <= 1'b0; 
						end
					3'b010: 
						begin
							next_state <= 3'b100; 
							data_out <=1'b0; 
							data_out_return1 <=1'b0; 
							data_out_return2 <= 1'b0; 
						end
					3'b011: 
						begin
							next_state <= 3'b111; 
							data_out <=1'b0; 
							data_out_return1 <=1'b0; 
							data_out_return2 <= 1'b0; 
						end
				endcase	
			3'b011: 
				case(data_in)
					3'b000: 
						begin
							next_state <= 3'b011; 
							data_out <=1'b0; 
							data_out_return1 <=1'b0; 
							data_out_return2 <= 1'b0; 
						end
					3'b001: 
						begin
							next_state <= 3'b100; 
							data_out <=1'b0; 
							data_out_return1 <=1'b0; 
							data_out_return2 <= 1'b0; 
						end
					3'b010: 
						begin
							next_state <= 3'b101; 
							data_out <=1'b0; 
							data_out_return1 <=1'b0; 
							data_out_return2 <= 1'b0; 
						end
					3'b011: 
						begin
							next_state <= 3'b000; 
							data_out <=1'b1; 
							data_out_return1 <=1'b0; 
							data_out_return2 <= 1'b0; 
						end
				endcase		
			3'b100: 
				case(data_in)
					3'b000: 
						begin
							next_state <= 3'b000; 
							data_out <=1'b0; 
							data_out_return1 <=1'b0; 
							data_out_return2 <= 1'b0; 
						end
					3'b001: 
						begin
							next_state <= 3'b101; 
							data_out <=1'b0; 
							data_out_return1 <=1'b0; 
							data_out_return2 <= 1'b0; 
						end
					3'b010: 
						begin
							next_state <= 3'b110; 
							data_out <=1'b0; 
							data_out_return1 <=1'b0; 
							data_out_return2 <= 1'b0; 
						end
					3'b011: 
						begin
							next_state <= 3'b000; 
							data_out <=1'b0; 
							data_out_return1 <=1'b0; 
							data_out_return2 <= 1'b0; 
						end
				endcase													
			3'b101: 
				case(data_in)
					3'b000: 
						begin
							next_state <= 3'b101; 
							data_out <=1'b0; 
							data_out_return1 <=1'b0; 
							data_out_return2 <= 1'b0; 
						end
					3'b001: 
						begin
							next_state <= 3'b110; 
							data_out <=1'b0; 
							data_out_return1 <=1'b0; 
							data_out_return2 <= 1'b0; 
						end
					3'b111: 
						begin
							next_state <= 3'b011; 
							data_out <=1'b0; 
							data_out_return1 <=1'b0; 
							data_out_return2 <= 1'b0; 
						end
					3'b011: 
						begin
							next_state <= 3'b000; 
							data_out <=1'b1; 
							data_out_return1 <=1'b0; 
							data_out_return2 <= 1'b1; 
						end
				endcase	
			3'b110: 
				case(data_in)
					3'b000: 
						begin
							next_state <= 3'b110; 
							data_out <=1'b0; 
							data_out_return1 <=1'b0; 
							data_out_return2 <= 1'b0; 
						end
					3'b001: 
						begin
							next_state <= 3'b111; 
							data_out <=1'b0; 
							data_out_return1 <=1'b0; 
							data_out_return2 <= 1'b0; 
						end
					3'b010: 
						begin
							next_state <= 3'b000; 
							data_out <=1'b1; 
							data_out_return1 <=1'b0; 
							data_out_return2 <= 1'b0; 
						end
				endcase	
			3'b111: 
				case(data_in)
					3'b000: 
						begin
							next_state <= 3'b111; 
							data_out <=1'b0; 
							data_out_return1 <=1'b0; 
							data_out_return2 <= 1'b0; 
						end
					3'b001: 
						begin
							next_state <= 3'b000; 
							data_out <=1'b1; 
							data_out_return1 <=1'b0; 
							data_out_return2 <= 1'b0; 
						end
				endcase		
always@(posedge clk ir rst_n)
	if(!rst_n)	
		current_state <= 3'b000;
	else
		current_state <= next_state;
endmodule						

例: "11010" シーケンス検出器
シーケンス検出器は、デジタル コード ストリームから指定されたシーケンスを検出します。シーケンス 11010 が入力に現れると出力は 1 になり、それ以外の場合は出力は 0 になります。ここでは、繰り返しシーケンスは考慮されません。つまり、指定されたシーケンスが出現した後にシーケンス検出が再開され、以前のデータは考慮されなくなります。データは右端から、つまり1-1-0-1-0の順に入力することが規定されている。シーケンス検出器の状態遷移図は次のとおりです。

ここに画像の説明を挿入

module seqdet(dout,din,restn,clk);
parameter IDLE = 3'd0, A = 3'd1, B = 3'd3, C = 3'd4, E = 3'd5;
output dout;
input din,rstn,clk;
reg[2:0] state,next_state;
wire dout;
assign dout = (state==E)?1:0;
always@(posedge clk or negedge rstn)
	if(!rstn)
		state = IDLE;
	else
		case(state)
			IDLE:
					if(din)
						next_state = A;
					else
						next_state = IDLE;
			A:	
				if(din)
					next_state = B;
				else
					next_state = IDLE;
			B:
				if(din)
					next_state = B;
				else
					next_state = C;
			C:
				if(din)
					next_state = D;
				else
					next_state = IDLE;
			D:
				if(din)
					next_state = B;
				else
					next_state = IDLE;
			E:
				if(din)
					next_state = IDLE;
				else
					next_state = A;
			default:
				next_state = IDLE;
		endcase
always@(posedge clk)
		state <= next_state;
endmodule

出典: Cai Jueping 教師の Verilog コース

おすすめ

転載: blog.csdn.net/KIDS333/article/details/127003907