Verilog HDL Tips もしくはドはまりした反省
レジスタのリセット
Verilogの言語仕様では左辺が右辺より大きい場合、
自動的に左辺の幅に合わせて足りない分が0で拡張される。
それを利用してparameterでビット幅が変わるようなレジスタのリセット
はとりあえず右辺に1'b0と書いておけばいい。
ex
自動的に左辺の幅に合わせて足りない分が0で拡張される。
それを利用してparameterでビット幅が変わるようなレジスタのリセット
はとりあえず右辺に1'b0と書いておけばいい。
ex
reg [3:0] a;
a = 1'b0; //これで問題ない
a = 0 //これだと右辺は32bitなので論理合成でWarnigが出る
reg [4:0] b,c,d;
{b,c,d} = 1'b0; //これも問題ない
条件演算子(セレクタ)
assign a = (x)? b : c;
xが真なら左のWireを偽なら右のWireをアサインする
センシティブ
reg Register;
always@(Register)begin(処理)end
こんな感じでposedgeやらnegedgeを付けずにセンシティブを書くとシミュレーションの場合
リセット時の不定値から0になった場合でも起動してしまうので注意。
リセット時の不定値から0になった場合でも起動してしまうので注意。
複数のセンシティブから同じレジスタに書き込んではいけない
always@(posedge Clock or posedge Reset) begin
if(Reset) begin
Count <= 0;
end else begin
Count <= Count + 1'b1;
end
end
always@(posedge AltClock) begin
Count <= Count + 1'b1;
end
上記のような書き方はNG。
実際のハードウェア構成では書き込みクロックを二つもつことはできないので論理合成ではねられる。
複数のクロックから書き込みたい場合はMUXを使ってクロックを選択する
実際のハードウェア構成では書き込みクロックを二つもつことはできないので論理合成ではねられる。
複数のクロックから書き込みたい場合はMUXを使ってクロックを選択する
センンシティブのクロックエッジは一つの信号につき一つにする
always @(posedge Clock or negdgede Clock) begin
上記のように書くと論理合成でエラーが出る。これもやはりD型フリップフロップの構造に由来する。
ひとつの信号につきクロックエッジは上昇端か下降端どちらかにすること。
ひとつの信号につきクロックエッジは上昇端か下降端どちらかにすること。
ビット指定
reg [7:0] Value;
reg [2:0] Select;
always@(posedge Value[Select])
上のように書くと文法エラーになる。レジスタのビット指定は定数、
またはparameterで指定しなければいけない。
またはparameterで指定しなければいけない。
数値の2の補数表現
4'd1 // = 4'b0001
-4'd1 // = 4'b1111
4'sd1 // = 4'b0001
-4'sd1 // = 4'b1111
ANSI C スタイルのModuleの書きかた
メリット
- ポート宣言とビット幅指定を一度に行えるのでコード量が減らせる
- defparamいらない
デメリット
- Verilog2001以上でしか使えない
例.
//モジュール定義例
module BitShifter
#(
parameter i = 4, //デフォルトのパラーメータ
parameter s = 2
)
(
input [i-1:0] in,
input [s-1:0] amt,
output [i-1:0] result
);
assign result = in<<amt;
endmodule
module tb_bs;
reg [7:0] in;
reg [2:0] amt;
wire [7:0] result;
//インスタン化宣言例
BitShifter #(.i(8),.s(3)) //パラーメータ上書き
bs (.in(in),.amt(amt),.result(result)); //インスタンス宣言
endmodule