平均化をVHDL,Verilogで設計する

平均化のデジタル回路設計で設計の概念を解説しましたので、実際にVHDLとVerilogで設計してみます。
まず、VHDLのソースコードを示します。
-- TITLE: "average.vhd" -- MODULE NAME: -- PROJECT CODE: -- AUTHOR: (****@nakaharagiken.com) -- CREATION DATE: 2020.8.22 -- SOURCE: -- LICENSE: Copyright (c) 2020 nakaharagiken All rights reserved. -- DESCRIPTION: 4回平均回路 -- NOTES TO USER: -- SOURCE CONTROL: -- REVISION HISTORY: v0.1 2020.8.22 First edition -- -- library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_unsigned.all; use IEEE.std_logic_arith.all; entity average is port ( clock: in std_logic; -- system clock nreset: in std_logic; -- asynchronous reset ____reset___|~~~normal~~~ indata: in std_logic_vector(7 downto 0); -- 入力データ avgdata: out std_logic_vector(7 downto 0) -- 出力 ); end entity average; architecture rtl of average is --------------------------------------------------------------- -- SIGNALS --------------------------------------------------------------- signal rDFF_A: std_logic_vector(7 downto 0); -- 8bitレジスタ signal rDFF_B: std_logic_vector(7 downto 0); -- 8bitレジスタ signal rDFF_C: std_logic_vector(7 downto 0); -- 8bitレジスタ signal rDFF_D: std_logic_vector(7 downto 0); -- 8bitレジスタ signal rDFF_Ans: std_logic_vector(7 downto 0); -- 8bitレジスタ signal wMulti_A: std_logic_vector(7 downto 0); -- 1/4データ signal wMulti_B: std_logic_vector(7 downto 0); -- 1/4データ signal wMulti_C: std_logic_vector(7 downto 0); -- 1/4データ signal wMulti_D: std_logic_vector(7 downto 0); -- 1/4データ begin ------------------------------------------ -- シフトレジスタ ------------------------------------------ process (clock,nreset) begin if nreset = '0' then -- リセット初期化 rDFF_A <= (others => '0'); rDFF_B <= (others => '0'); rDFF_C <= (others => '0'); rDFF_D <= (others => '0'); elsif clock' event and clock = '1' then -- clock 立ち上がり指示 rDFF_A <= indata; rDFF_B <= rDFF_A; rDFF_C <= rDFF_B; rDFF_D <= rDFF_C; end if; end process; ------------------------------------------ -- 1/4計算=右2ビットシフト -- 7 6 5 4 3 2 1 0 -- 0 0 7 6 5 4 3 2 1 0 ------------------------------------------ wMulti_A <= "00" & rDFF_A(7 downto 2); wMulti_B <= "00" & rDFF_B(7 downto 2); wMulti_C <= "00" & rDFF_C(7 downto 2); wMulti_D <= "00" & rDFF_D(7 downto 2); ------------------------------------------ -- 答えのラッチ ------------------------------------------ process (clock,nreset) begin if nreset = '0' then rDFF_Ans <= (others => '0'); elsif clock' event and clock = '1' then rDFF_Ans <= wMulti_A + wMulti_B + wMulti_C + wMulti_D; -- 加算 end if; end process; avgdata <= rDFF_Ans; end architecture rtl;
47行目から8ビット×4段のシフトレジスタを作成しています。簡単にするためにクロック同期そのままで設計しています。実際に使う時にはイネーブル等でクロックを間引く事も必要になるでしょう。
64行目から1/4の回路なので説明が必要です。平均化のデジタル回路設計で解説したように、予めシフトレジスタの値を1/4にするのですが、右にビットシフトを2bitします。2bitと言っても一気に2bitできるので、この書き方を覚えてください。
wMulti_A <= “00” & rDFF_A(7 downto 2); はMSB側の2ビットに00を入れて、下位側はrDFF_Aの7ビット目から2ビット目までを入れます。このようにすることで、右2bitシフトしています。図で説明すると次のようになります。

rDFF_Aが右に2ビット分ズレているのがわかるでしょうか? rDFF_A[7]はwMulti_A[5]に入力されています。つまり、1ビットずつ記載するのであれば次のようになります。
wMulti_A(7) <= ‘0’;
wMulti_A(6) <= ‘0’;
wMulti_A(5) <= rDFF_A(7);
wMulti_A(4) <= rDFF_A(6);
wMulti_A(3) <= rDFF_A(5);
wMulti_A(2) <= rDFF_A(4);
wMulti_A(1) <= rDFF_A(3);
wMulti_A(0) <= rDFF_A(2);
上記のように1bitずつバラバラに記載するのも良いですし、wMulti_A <= “00” & rDFF_A(7 downto 2); のように1行で記載しても良いです。結果は同じです。これは記載するエンジニアの好みですが、wMulti_A <= “00” & rDFF_A(7 downto 2);のように1行で記述する方が多いのではないでしょうか。8bitぐらいでしたら、バラバラに書けるのですが、32bitぐらいになると面倒になってきますし、記述誤りが発生します。
これは経験上の話ですが、意外にバラバラに記載してその中の1行が間違っている。というのを見つけるのは結構難しく感じます。だいたい実行結果から、ビットシフトの中に記述間違いがある。とわかるのですが、それがどのビットなのかを探すのは結構大変です。その点1行で書いていれば、必ずその1行の中に誤り(バグ)があるので、見つけるのは容易です。
右2ビットシフトの場合、MSB側の2ビットを捨てているので、これが誤差となります。信号であればノイズになります。平均化した値の用途によってはこの誤差を許さない場合がありますので、そのような場合には、1/4する時に誤差が生じないようにビットを一旦拡大する。等の処置が必要になります。
74行目からは計算結果をラッチ(フリップフロップ)しています。ラッチという言葉はこの場合誤っているのですが、現場ではデータを最後に揃えるような時にも「ラッチ」という言い回しをします。
81行目が加算している部分です。単純に足し算です。これは予め1/4しているので、rDFF_Ansのビット数が加算した値をオーバーフローしない。とわかっているのでできる計算です。このようにオーバーフローしない。とわかっている。というポイントは重要です。もし、わかっていない場合には、オーバーフローしても良いようにビットを広げるか、オーバーフローを検出するような回路を追加する必要があります。
最後に、Verilogで同じ回路を記載した例を示します。
// TITLE: "average.v" // MODULE NAME: // PROJECT CODE: // AUTHOR: (****@nakaharagiken.com) // CREATION DATE: 2020.8.23 // SOURCE: // LICENSE: Copyright (c) 2020 nakaharagiken All rights reserved. // DESCRIPTION: 4回平均回路 // NOTES TO USER: // SOURCE CONTROL: // REVISION HISTORY: v0.1 2020.8.23 First edition // // `timescale 1ns/1ps module average( clock, // in std_logic; -- system clock nreset, // in std_logic; -- asynchronous reset ____reset___|~~~normal~~~ indata, // in std_logic_vector(7 downto 0); -- 入力データ avgdata // out std_logic_vector(7 downto 0) -- 出力 ); input clock; // in system clock input nreset; // in asynchronous reset ____reset___|~~~normal~~~ input [7:0] indata; // in std_logic_vector(7 downto 0); -- 入力データ output [7:0] avgdata; // out std_logic_vector(7 downto 0) -- 出力 /////////////////////////////////////////////////////////////// // SIGNALS /////////////////////////////////////////////////////////////// reg [7:0] rDFF_A; // 8bitレジスタ reg [7:0] rDFF_B; // 8bitレジスタ reg [7:0] rDFF_C; // 8bitレジスタ reg [7:0] rDFF_D; // 8bitレジスタ reg [7:0] rDFF_Ans; // 8bitレジスタ wire [7:0] wMulti_A; // 1/4データ wire [7:0] wMulti_B; // 1/4データ wire [7:0] wMulti_C; // 1/4データ wire [7:0] wMulti_D; // 1/4データ ////////////////////////////////////////// // シフトレジスタ ////////////////////////////////////////// always @ (posedge clock, negedge nreset) begin if (!nreset) begin rDFF_A <= 8'h00; rDFF_B <= 8'h00; rDFF_C <= 8'h00; rDFF_D <= 8'h00; end else begin rDFF_A <= indata; rDFF_B <= rDFF_A; rDFF_C <= rDFF_B; rDFF_D <= rDFF_C; end end ////////////////////////////////////////// // 1/4計算=右2ビットシフト // 7 6 5 4 3 2 1 0 // 0 0 7 6 5 4 3 2 1 0 ////////////////////////////////////////// assign wMulti_A = {2'b00,rDFF_A[7:2]}; assign wMulti_B = {2'b00,rDFF_B[7:2]}; assign wMulti_C = {2'b00,rDFF_C[7:2]}; assign wMulti_D = {2'b00,rDFF_D[7:2]}; ////////////////////////////////////////// // 答えのラッチ ////////////////////////////////////////// always @ (posedge clock, negedge nreset) begin if (!nreset) begin rDFF_Ans <= 8'h00; end else begin rDFF_Ans <= wMulti_A + wMulti_B + wMulti_C + wMulti_D; // 加算 end end assign avgdata = rDFF_Ans; endmodule
-
前の記事
平均化のデジタル回路設計 2020.08.22
-
次の記事
Verilogでの配列 2020.08.29

コメントを書く