⭐
FPGA超入門 その4-並列処理/逐次処理-
例
似たような記述の下記のようなソースコード(抜粋)があります。
VHDLの例
VHDL1
signal A,B,C : std_logic_vector(3 downto 0) := "0000";
process(CLK) begin
if(CLK'event and CLK = '1') then
A <= A + 1;
B <= A + 1;
C <= A + B;
end if;
end process;
VHDL2
process(CLK)
variable A,B,C : std_logic_vector(3 downto 0) := "0000";
begin
if(CLK'event and CLK = '1') then
A := A + 1;
B := A + 1;
C := A + B;
end if;
end process;
verilogの例
verilog1
reg [3:0] A = 4'd0;
reg [3:0] B = 4'd0;
reg [3:0] C = 4'd0;
always@(posedge CLK) begin
A <= A + 4'd1;
B <= A + 4'd1;
C <= A + B;
end
verilog2
reg [3:0] A = 4'd0;
reg [3:0] B = 4'd0;
reg [3:0] C = 4'd0;
always@(posedge CLK) begin
A = A + 4'd1;
B = A + 4'd1;
C = A + B;
end
一見同じように見えますが、VHDLでは<=と:=、verilogでは<=と=というように代入の仕方が異なっています。~1の方はノンブロッキング代入、~2の方はブロッキング代入と呼ばれ、それぞれ回路構成が異なってきます。
動作
実際に上記を動作させると、~1の方は
初期値 | 1clk目 | 2clk目 | 3clk目 | |
---|---|---|---|---|
A | 0 | 1 | 2 | 3 |
B | 0 | 1 | 2 | 3 |
C | 0 | 0 | 2 | 4 |
~2の方は | ||||
初期値 | 1clk目 | 2clk目 | 3clk目 | |
---- | ---- | ---- | ---- | ---- |
A | 0 | 1 | 2 | 3 |
B | 0 | 2 | 3 | 4 |
C | 0 | 3 | 5 | 7 |
と進み、全く別の動作となっています。 | ||||
ノンブロッキング代入は並列的に同時に処理がされます。A,B,Cそれぞれが1clk前のA,Bの値から計算されています。クロックのタイミングでその時の値から同時に計算されていると考えればよいでしょうか。 | ||||
ブロッキング代入は逐次的に処理がされます。Aの計算後、そのAの値を使ってBが計算され、そのBの値を使ってさらにCが順番に計算されています。一般的なソフトの記述としてはこちらの方がしっくりくるでしょうか。 |
VHDL3
process(CLK)
variable A,B,C : std_logic_vector(3 downto 0) := "0000";
begin
if(CLK'event and CLK = '1') then
C := A + B;
B := A + 1;
A := A + 1;
end if;
end process;
のように順番を変えれば、~1と同じ動作にはなると思いますが、混乱の原因となりますので、process文、always文内ではノンブロッキング代入とするのが一般的です。
Discussion