階層構造を意識した設計スタイルとは?:触って学ぼう FPGA開発入門(5)(2/4 ページ)
大規模回路の場合、1つのモジュールで設計を行うことは難しい。ここでは、大規模回路で用いられる階層構造での記述について解説します
インスタンスの記述方法
10進アップ・ダウンカウンタと7セグメントLEDデコーダを接続します。リスト3のように1つのファイルに両方を記述する、つまり階層構造を用いない記述でも構いませんが、ここでは大規模回路で用いられる階層構造を意識した記述方法を用います。
1 module UPDOWN_7SEG(RESET, CLK, DEC, LED, SA); 2 input RESET, CLK, DEC; 3 output [7:0] LED; 4 output [3:0] SA; 5 6 parameter SEC1_MAX = 6000000; // 6MHz 7 8 assign SA = 4'bzzz0; 9 10 reg [22:0] tmp_count; 11 reg [3:0] COUNT_TMP; 12 wire ENABLE; 13 reg [7:0] LED; 14 15 always @(posedge CLK or negedge RESET) 16 begin 17 if (RESET == 1'b0) 18 tmp_count <= 23'h000000; 19 // else 20 else if (ENABLE == 1'b1) 21 tmp_count <= 23'h000000; 22 else 23 tmp_count <= tmp_count + 23'h1; 24 end 25 26 // assign DIVIDE_CLK = tmp_count[22]; 27 assign ENABLE = (tmp_count == (SEC1_MAX - 1))? 1'b1 : 1'b0; 28 29 //always @(posedge DIVIDE_CLK or negedge RESET) 30 always @(posedge CLK or negedge RESET) 31 begin 32 if (RESET == 1'b0) 33 COUNT_TMP <= 4'h0; 34 else if (ENABLE == 1'b1) 35 // else if (DEC == 1'b1) 36 if (DEC == 1'b1) 37 if (COUNT_TMP == 4'h9) 38 COUNT_TMP <= 4'h0; 39 else 40 COUNT_TMP <= COUNT_TMP + 4'h1; 41 else 42 if (COUNT_TMP == 4'h0) 43 COUNT_TMP <= 4'h9; 44 else 45 COUNT_TMP <= COUNT_TMP - 4'h1; 46 end 47 48 always @(COUNT_TMP) 49 begin 50 case(COUNT_TMP) //ABCDEFG Dp 51 4'b0000:LED <= 8'b0000001_1; 52 4'b0001:LED <= 8'b1001111_1; 53 4'b0010:LED <= 8'b0010010_1; 54 4'b0011:LED <= 8'b0000110_1; 55 4'b0100:LED <= 8'b1001100_1; 56 4'b0101:LED <= 8'b0100100_1; 57 4'b0110:LED <= 8'b0100000_1; 58 4'b0111:LED <= 8'b0001101_1; 59 4'b1000:LED <= 8'b0000000_1; 60 4'b1001:LED <= 8'b0000100_1; 61 default:LED <= 8'b0110000_1; 62 endcase 63 end 64 endmodule
リスト3 階層構造を用いない10進アップ・ダウンカウンタ+7セグメントLEDデコーダの記述(UPDOWN_7SEG-2.v) |
階層構造を用いるといっても、それほど難しいことではありません。単に図1の接続となるように10進アップ・ダウンカウンタと7セグメントLEDデコーダのモジュールをそれぞれインスタンス(箱を置く)して接続するだけです。インスタンスした記述をリスト4に示します。
1 module UPDOWN_7SEG(RESET, CLK, DEC, LED, SA); 2 input RESET, CLK, DEC; 3 output [7:0] LED; 4 output [3:0] SA; 5 6 wire [3:0] COUNT; 7 8 parameter SEC1_MAX = 6000000; // 6MHz 9 10 UPDOWN #(.SEC1_MAX(SEC1_MAX)) i0(.RESET(RESET), .CLK(CLK), .DEC(DEC), .COUNT(COUNT)); 11 DECODER7 i1(.COUNT(COUNT), .LED(LED), .SA(SA)); 12 13 endmodule
リスト4 10進アップ・ダウンカウンタ+7セグメントLEDでコーダのインスタンス記述(UPDOWN_7SEG.v) |
これまで、インスタンスの記述方法に関してあまり詳しく説明してこなかったので、ここで少し解説します。
10、11行目に10進アップ・ダウンカウンタと7セグメントLEDデコーダのモジュールをそれぞれインスタンスしています。記述方法は以下のとおりです。
UPDOWN #(.SEC1_MAX(SEC1_MAX)) i0(.RESET(RESET), .CLK(CLK), .DEC(DEC), .COUNT(COUNT)); DECODER7 i0(.COUNT(COUNT), .LED(LED), .SA(SA)); ↑ 同じインスタンス名を使用してはいけない
また、この例ではドット付きの(例えば.RESET)パラメータ名、ポート名と「()」内の接続したいパラメータ、信号名の名前を一致させていますが、必ずしも同じである必要はありません。
さらに、このインスタンスの記述部分がRTLの最上位記述となるため、少し冗長に見えますが、parameter文で再度SEC1_MAXを6000000に指定して、下位の10進アップ・ダウンカウンタにそのパラメータの値を渡しています。
defparam構文で階層的にパラメータを渡すことができる方法もありますが、論理合成ツールによってはこのパラメータを階層的に渡すという記述方法に対応していないものもありますので、ここではリスト4の記述を採用しました。
モジュール名 #(.モジュール内のパラメータ名(渡したいパラメータ), ……) インスタンス名(.モジュールのポート名(接続したい信号名), ……);
この記述で特に気を付けなければいけないのが、インスタンス名です。任意の名前を付けられますが、同じモジュール内ではユニークな名前である必要があります。つまり、同じインスタンス名を用いることができないという文法的なルールがあるのです。
以下のように、モジュール名が違っているからといって、同じ「i0」というインスタンス名を使用してはいけません。
Copyright © ITmedia, Inc. All Rights Reserved.