※上記の広告は60日以上更新のないWIKIに表示されています。更新することで広告が下部へ移動します。

Verilog HDL Tips もしくはドはまりした反省


レジスタのリセット

Verilogの言語仕様では左辺が右辺より大きい場合、
自動的に左辺の幅に合わせて足りない分が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になった場合でも起動してしまうので注意。

複数のセンシティブから同じレジスタに書き込んではいけない

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を使ってクロックを選択する

センンシティブのクロックエッジは一つの信号につき一つにする

always @(posedge Clock or negdgede Clock) begin
 
上記のように書くと論理合成でエラーが出る。これもやはりD型フリップフロップの構造に由来する。
ひとつの信号につきクロックエッジは上昇端か下降端どちらかにすること。

ビット指定

reg [7:0] Value;
reg [2:0] Select;
always@(posedge Value[Select])
 
上のように書くと文法エラーになる。レジスタのビット指定は定数、
または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