エッジ検出の書き方
「信号の立ち上がりエッジを検出する回路は次の書き方にする」
○ shift_reg[1:0] <= {shift_reg[0],shift_in}; // シフトレジスタ if(shift_reg[1:0]==2'b01) ... // 立ち上がりエッジの検出 if(shift_reg[1:0]==2'b10) ... // 立ち下がりエッジの検出 |
次のように書くと立ち上がりなのか立ち下がりなのか見分けにくい
× shift_reg0 <= shift_in; // シフトレジスタ shift_reg1 <= shift_reg0; // シフトレジスタ if(shift_reg0 & ~shift_reg1) ... // 立ち上がりエッジの検出 if(~shift_reg1 & shift_reg0) ... // 立ち上がりエッジの検出 |
またチャタリングを除去してエッジ検出するときも同じスタイルで書ける
○ shift_reg[3:0] <= {shift_reg[2:0],shift_in}; // シフトレジスタ if(shift_reg[3:0]==4'b0111) ... // 立ち上がりエッジの検出 |
シフトは演算子>>,<<でも書けるが、シフト量が定数のときはシフト演算子を使わずに明示的に書いた方がよい。
× shift_reg <= (shift_reg << 1) | shift_in; // シフトレジスタ ○ shift_reg[1:0] <= {shift_reg[0],shift_in}; // シフトレジスタ |
というのは、レアケースだがシフト演算子を使うとビット幅の扱いを間違えることがあるからである。
次の例では(a+b)>>1は、(a+b)が16ビットに切り捨てられて、その後にシフトされるのでキャリが失われる。正しくは一旦ビット幅が広いtmp=a+bに入れてからシフトしなければならない。
// 平均(a+b)/2の計算 reg[15:0] a_reg,b_reg,avg_reg; wire[16:0] tmp; × avg_reg <= (a_reg + b_reg) >> 1; // キャリが失われて結果が間違い ○ tmp = a_reg + b_reg; // キャリは保持される avg_reg <= tmp[16:1]; |