VHDLとVerilog-HDLの記述方法についてメモ.
VHDLとVerilog-HDLではほとんど記号的な記述方法に差があるのみで, ほとんどが機械的に可換である. 以下では機械的には置き換えられない記述方法についてメモしておく. ほとんどは書き方の問題で実装時に有利・不利があるかは考えていない.
また筆者がVHDLをメインに使っているためVHDLの特殊な記法に言及しているようなものだ.
コンポーネント宣言
悪名高いVHDLのコンポーネント宣言. ライブラリ宣言の問題でしかない.
カウンタ
Verilogではビット幅を指定せずに整数を宣言すると32ビットとして解釈される. 安全のために信号の幅はきちんと揃えておくべき. これがカウンタだといちいちビット幅を考える必要があるので面倒.
Verilog
reg [3:0] cnt; // Counter | |
~ | |
always @(negedge nRST, posedge CLK) begin | |
if (~ nRST) | |
cnt <= 4'd0; | |
else if (CLK) begin | |
if (cnt == CntMax) | |
cnt <= 4'd0; | |
else | |
cnt <= cnt + 4'd1; | |
end | |
end |
VHDLでは算術演算子がオーバーロードファンクションとして定義されているため, std_logic_vector
だろうがinteger
だろうが関係なく扱える.
VHDL
cnt : integer range 0 to CntMax -- Counter | |
~ | |
process (CLK, nRST) begin | |
if (nRST = '0') then | |
cnt <= 0; | |
elsif (CLK'event and CLK = '1') then | |
if (cnt = CntMax) then | |
cnt <= 0; | |
else | |
cnt <= cnt + 1; | |
end if; | |
end if; | |
end process; |
集合体(Aggregate)
VHDLはベクタに集合体を代入することができる. a <= (others => '0')
も集合体の代入. これを使えばエンコーダがすっきりする.
a : std_logic_vector(7 downto 0); | |
b : std_logic_vector(3 downto 0); | |
~ | |
process (CLK, nRST) begin | |
if (nRST = '0') then | |
a <= (others => '0'); | |
elsif (CLK'event and CLK = '1') then | |
case (b) is | |
when X"0" => a <= (0 => '1', others => '0'); | |
when X"1" => a <= (1 => '1', others => '0'); | |
when X"2" => a <= (2 => '1', others => '0'); | |
when X"3" => a <= (3 => '1', others => '0'); | |
when X"4" => a <= (4 => '1', others => '0'); | |
when X"5" => a <= (5 => '1', others => '0'); | |
when X"6" => a <= (6 => '1', others => '0'); | |
when X"7" => a <= (7 => '1', others => '0'); | |
when others => a <= (others => '0'); | |
end case | |
end if; | |
end process; |
列挙型(Enumeration)
VHDLでtype宣言と呼ばれるやつ. Verilogでは列挙型をサポートしない. ステートマシンの宣言が異なる.
VHDL
-- State machine -- | |
type main_state is ( | |
WakeUp, -- Device wake up | |
Init, -- Initialization | |
Idle, -- Idle | |
StateA, -- State A | |
StateB, -- State B | |
TurnAround -- Turn around idle | |
); | |
signal main_st : main_state; |
Verilog
// State machine // | |
parameter WakeUp = 6'd000001; // Device wake up | |
parameter Init = 6'd000010; // Initialization | |
parameter Idle = 6'd000100; // Idle | |
parameter StateA = 6'd001000; // State A | |
parameter StateB = 6'd010000; // State B | |
parameter TurnAround = 6'd100000; // Turn around idle | |
reg [2:0] main_st; // State machine |
System Verilogで列挙型がサポートされた.
System Verilog
typedef enum logic [2:0] { | |
WakeUp, // Device wake up | |
Init, // Initialization | |
Idle, // Idle | |
StateA, // State A | |
StateB, // State B | |
TurnAround // Turn around idle | |
} main_st; |
アトリビュート
VHDLではアトリビュートによってビット数を意識せずにビット位置の指定ができる.
ex. シフトレジスタ
シフトレジスタではビット幅を全く意識せずに記述することができる.
process (CLK, nRST) begin | |
if (nRST = '0') then | |
a <= (others => '0'); | |
elsif (CLK'event and CLK = '1') then | |
a <= a(a'left - 1 downto 0) & in_a; | |
end if; | |
end process; |
ex. 乗算器
算術演算では頻繁にビット幅が変わるが, いちいち計算しなくてもよい.
a : std_logic_vector(3 downto 0); | |
b : std_logic_vector(3 downto 0); | |
product : std_logic_vector(a'length + b'length - 1 downto 0); | |
~ | |
product <= a * b; |
リダクション演算子
Verilogではリダクション演算子をサポートする.
Verilog
parameter a = 4'b1010; | |
assign b = or a; // b:1'b1 | |
assign c = and a; // c:1'b0 |
VHDLではstd_logic_1164でサポートしないが, std_logic_miscで使うことができる.
VHDL
constant : std_logic_vector(3 downto 0) := "1010"; | |
b <= or_reduce(a); | |
c <= and_reduce(a); |
またVHDL-2008でVerilogのようなリダクション演算子がサポートされたようだ. なおQuartusはLite, Standard editionではVHDL-2008未対応.
多次元配列
Verilogでは行列のような3次元以上の多次元配列を扱えない. VHDLでは2次元配列と同様に扱える. 簡単な2×2行列くらいなら2次元化しても問題ないが, テンソルを扱ったりする場合は有用(テンソル使うか?).
type MatrixTyp is array (0 to 2, 0 to 2) of std_logic_vector(7 downto 0); | |
signal matrix_cell : MatrixTyp; -- Matrix cells | |
~ | |
matrix_cell(0, 0) <= a00; | |
matrix_cell(0, 1) <= a01; | |
matrix_cell(0, 2) <= a02; | |
matrix_cell(1, 0) <= a10; | |
matrix_cell(1, 1) <= a11; | |
matrix_cell(1, 2) <= a12; | |
matrix_cell(2, 0) <= a20; | |
matrix_cell(2, 1) <= a21; | |
matrix_cell(2, 2) <= a22; |
0 件のコメント:
コメントを投稿