クロックなどの信号によって状態が変化する順序回路は、always文を用いて設計する。always文では指定した信号に変化(立上り、立下り)があった時に行う処理を記述する。
レジスタの設計
実習1. 4ビットレジスタの設計
以下の register4.v で設計される回路を実習ボードに実装して、動作を確かめること。
ただし top-level entity は register4 とする。
入出力の割り当ては表の通りにすること。
`default_nettype none
module register4(
input wire clock,
input wire [3:0] data,
output reg [3:0] q
);
always @ (posedge clock) begin // センシティビティリスト
// clock の立上りのタイミングでalways文が起動
q <= data; // ノンブロッキング代入
end
endmodule
register4のポート | I/O デバイス | 備考 |
---|---|---|
clock | GCLK3 (プッシュスイッチ) | ジャンパピンJP10を右側に設置して利用する。ボタン押下げ時に1 |
data[3:0] | SA3~SA0(トグルスイッチ) | |
q[3:0] | DA3~DA0(個別LED) |
### 解説
always文では、センシティビティリスト(always @
に続く()
内)に起動のタイミングを記述し、その起動のタイミングで実行される処理を引き続く文(通常はbegin~end
で囲まれる複文)で記述する。
always @ (<センシティビティリスト>)
<センシティビティリストの信号に変化があった時に実行される文>;
// 複数の処理を行いたい場合(複文)はbegin ~ endで囲む
- センシティビティリストに指定された信号に変化があったタイミングでalways文が起動し処理が実行される
- センシティビティリストでは、
posedge
で立上り、negedge
で立下りを指定する - 実習1ではセンシティビティリストに
posedge clock
と記述することで、clockの立上りのタイミングで処理を行うことを指定している - クロックなどの信号の変化のタイミングでレジスタに値を代入するような処理を行いたい場合は、alwaysで起動される文において、レジスタ型(reg型)変数へノンブロッキング代入
<=
で値を代入するように記述するとよい - 実習1では、clockの立上りのタイミングで、4ビットのreg型変数
q
に4ビットの信号data
を代入し、その後、代入された信号を保持する回路を記述している(動作例を参照)
実習2. 同期式リセット付きレジスタの設計
以下の register4_sync_reset.v で設計される回路を実習ボードに実装して、動作を確かめること。
ただし top-level entity は register4_sync_reset とする。
入出力の割り当ては表の通りにすること。
`default_nettype none
module register4_sync_reset(
input wire clock,
input wire n_reset, // リセット(active low)
input wire [3:0] data,
output reg [3:0] q
);
always @ (posedge clock) begin
// clockの立上りでalways文が起動
if (n_reset == 1'b0) begin
q <= 4'b0; // n_resetがアクティブならリセット
end else begin
q <= data;
end
end
endmodule
register4_sync_resetのポート | I/O デバイス | 備考 |
---|---|---|
clock | GCLK3 (プッシュスイッチ) | ジャンパピンJP10を右側に設置して利用する。ボタン押下げ時に1 |
n_reset | S1 (プッシュスイッチ) | ボタン押下げ時に0(GND) |
data[3:0] | SA3~SA0(トグルスイッチ) | |
q[3:0] | DA3~DA0(個別LED) |
解説
alwaysで起動する文では if文やcase文を記述することができる
- 実習2では
clock
の立上りのタイミングでn_reset
の値を判定し、その判定結果で異なる動作を行うような回路を記述している
実習3. 非同期式リセット付きレジスタの設計
以下の register4_async_reset.v で設計される回路を実習ボードに実装して、動作を確かめること。
ただし top-level entity は register4_async_reset とする。
入出力の割り当ては表の通りにすること。
`default_nettype none
module register4_async_reset(
input wire clock,
input wire n_reset, // リセット(active low)
input wire [3:0] data,
output reg [3:0] q
);
always @ (posedge clock, negedge n_reset) begin
// clockの立上り、またはn_resetの立下りのタイミングでalways文が起動
if (n_reset == 1'b0) begin
q <= 4'b0; // n_resetがアクティブならリセット
end else begin
q <= data;
end
end
endmodule
register4_async_resetのポート | I/O デバイス | 備考 |
---|---|---|
clock | GCLK3 (プッシュスイッチ) | ジャンパピンJP10を右側に設置して利用する。ボタン押下げ時に1 |
n_reset | S1 (プッシュスイッチ) | ボタン押下げ時に0(GND) |
data[3:0] | SA3~SA0(トグルスイッチ) | |
q[3:0] | DA3~DA0(個別LED) |
解説
センシティビティリストには複数の信号を指定することができる
- 実習3では、センシティビティリストに
posedge clock, negedge n_reset
を指定することで、clock
の立上りとn_reset
の立下りの両方のタイミングで起動する回路を記述している
カウンタの設計
実習4. 5進カウンタの設計
以下の counter5.v で設計される回路を実習ボードに実装して、動作を確かめること。
ただし top-level entity は counter5 とする。
入出力の割り当ては表の通りにすること。
`default_nettype none
module counter5(
input wire clock,
output reg [2:0] count
);
always @ (posedge clock) begin
if (count >= 3'b100) begin
count <= 3'b000;
end else begin
count <= count + 1'b1;
end
end
endmodule
counter5のポート | I/O デバイス |
---|---|
clock | GCLK3 (プッシュスイッチ) |
count[2:0] | DA2~DA0(個別LED) |
実習5. デコーダ付き5進カウンタの設計 (モジュール設計)
以下の counter5_decoder.v, register3.v, mod5_inc.v, decoder.v で設計される回路を実習ボードに実装して、動作を確かめること。
ただし top-level entity は counter5_decoder とする。
入出力の割り当ては表の通りにすること。
module counter5_decoder(
input wire clock,
output wire [7:0] y
);
wire [2:0] count; // 現在のカウント値
wire [2:0] count_next; // 次のカウント値
register3 register( // 現在のカウント値を保持する3ビットレジスタ
.clock (clock),
.data (count_next),
.q (count)
);
mod5_inc mod5_inc( // 現在のカウント値から次のカウント値を求める次状態関数 y = x + 1 mod 5
.x (count),
.y (count_next)
);
decoder decoder( // 現在のカウント値をデコードして出力する出力関数
.num (count),
.y (y)
);
endmodule
`default_nettype none
module register3( // 3ビットレジスタ
input wire clock,
input wire [2:0] data,
output reg [2:0] q
);
always @ (posedge clock) begin
q <= data;
end
endmodule
`default_nettype none
module mod5_inc( // 5進カウント用の次状態関数(組合せ論理回路)
input wire [2:0] x,
output reg [2:0] y
);
always @ (*) begin
if (x >= 3'b100) begin
y = 3'b000;
end else begin
y = x + 1'b1;
end
end
endmodule
`default_nettype none
module decoder( // 出力関数(組合せ論理回路)
input wire [2:0] num,
output reg [7:0] y
);
always @ (*) begin
case (num)
3'b000: y = 8'b11111110;
3'b001: y = 8'b11111101;
3'b010: y = 8'b11111011;
3'b011: y = 8'b11110111;
3'b100: y = 8'b11101111;
3'b101: y = 8'b11011111;
3'b110: y = 8'b10111111;
3'b111: y = 8'b01111111;
endcase
end
endmodule
counter5_decoderのポート | I/O デバイス |
---|---|
clock | GCLK3 (プッシュスイッチ) |
y[7:0] | DA7~DA0(個別LED) |
解説
順序回路を設計する際は、現在の状態を保持する記憶部(レジスタ)、現在の状態と入力信号から次の状態を算出する次状態関数回路(組合せ論理回路)、現在の状態(および入力信号)から出力信号を算出する出力関数回路(組合せ論理回路)のそれぞれをモジュールとして設計し、それらを組み合わせて構築するとよい。
課題5における記憶部、次状態関数回路、出力関数回路は以下に示されるモジュールで設計されている。
- 記憶部: register3モジュール
- 次状態関数回路(組合せ論理回路): mod5_incモジュール
- 出力関数回路(組合せ論理回路): decoderモジュール
状態マシンの設計
実習6. 一時停止機能付きグレイコードカウンタの設計
以下の gray_counter.v, next_state_function.v, register2.v で設計される回路を実習ボードに実装して、動作を確かめること。
ただし top-level entity は gray_counter とする。
入出力の割り当ては表の通りにすること。
`default_nettype none
module gray_counter(
input wire clock,
input wire pause,
output wire [1:0] y
);
wire [1:0] state_now; // 現在の状態
wire [1:0] state_next; // 次の状態
// 次状態関数
next_state_function next_state_function(
.pause (pause),
.state_now (state_now),
.state_next (state_next));
// 記憶部 (2-bit register)
register2 register2(
.clock (clock),
.data (state_next),
.q (state_now));
// 出力関数
assign y = state_now;
endmodule
`default_nettype none
// 次状態関数: 現在の状態と入力から次の状態を出力する組合せ論理回路
module next_state_function(
input wire pause,
input wire [1:0] state_now,
output reg [1:0] state_next
);
// module 内でのパラメータ定義(各状態のビット表現の定義)
localparam Sa = 2'b00;
localparam Sb = 2'b01;
localparam Sc = 2'b11;
localparam Sd = 2'b10;
always @ (*) begin
case ({pause, state_now}) // 状態遷移表を記述する
{1'b0, Sa}: state_next = Sb;
{1'b0, Sb}: state_next = Sc;
{1'b0, Sc}: state_next = Sd;
{1'b0, Sd}: state_next = Sa;
{1'b1, Sa}: state_next = Sa;
{1'b1, Sb}: state_next = Sb;
{1'b1, Sc}: state_next = Sc;
{1'b1, Sd}: state_next = Sd;
endcase
end
endmodule
`default_nettype none
// 2-bit レジスタ: 現在の状態を保持する
module register2 (
input wire clock,
input wire [1:0] data,
output reg [1:0] q
);
always @ (posedge clock) begin
q <= data;
end
endmodule
gray_counterのポート | I/O デバイス |
---|---|
clock | GCLK3(プッシュスイッチ) |
pause | SA0(トグルスイッチ) |
y[1:0] | DA1~DA0(個別LED) |
解説
課題6における記憶部、次状態関数回路以下に示されるモジュールで設計されている。
- 記憶部: register2モジュール
- 次状態関数回路(組合せ論理回路): next_state_functionモジュール
出力関数については、今回、各状態を表す2ビットのビット表現を出力信号と同じになるようにしたため、特にモジュールとしては設計を行っていない。あえて言えば、gray_counterモジュール内の assign y = state_now;
の記述が出力関数に相当する。