isesimutil (r230) | 2012-01-01 23:07 |
nbox_util (r247) | 2012-03-11 22:19 |
noodlybox (0012) | 2010-01-01 19:46 |
TimingChartViewer (r245) | 2012-02-15 00:10 |
ステートマシンの書き方と、それには直接関係ないけれど知っておくと特になることのまとめ。
古い教科書などでは整数を扱うのにuse ieee.std_logic_unsigned.all;と書いてあることが多いです。 しかし、std_logic_unsignedとかstd_logic_arithとかは処理系によってふるまいが違うらしく、新しいソースではnumeric_stdを使うほうがよいです。 型変換に関しては http://marsee101.blog19.fc2.com/blog-entry-2344.html を見ると参考になると思います。
Verilog HDLと比べてVHDLで面倒くさいのが、いちいちcomponent宣言を用意しないとentityをインスタンシエートできないことなのですが、
のようにentity work.を呼び出すentityの前につけることで、component宣言を不要にできます。
一例として、ここに載せてあるソースの命名規則を以下に示します。
種類 | 命名 | 備考 |
入力ポート | I_~ | ポートは全部大文字 |
出力ポート | O_~ | |
入出力ポート | IO_~ | |
パラメータ | G_~ | Genericの頭文字 |
constant | C_~ | Constantの頭文字 |
負論理 | ~_N | |
イネーブル信号 | ~_ENA | 少し長いが、_ENだと負論理と区別しにくいので |
ステートマシンを書くとき、process (~)節の中に少しでも書き忘れがあるとラッチが推論される回路になってしまいます。 組み合わせ回路になるようにするには、以下のようにする必要があります。
ラッチが推論されていないことを確かめるには、ソースを眺めるよりもツールで合成をしてWarningを調べるほうが確実です。 以下に、各ツールでラッチが生成されたとき出るWarningをまとめます。
ツール | メッセージ |
Xilinx XST | WARNING:Xst:737 - Found n-bit latch for signal <信号名> |
Xilinx Vivado | |
Altera QuartusII |
StateMachineVerilog ページに添付してあるstatemachine_yyyymmdd.zipを拾っていってください。
- -- I_KICK入力があってからG_COUNTクロック後にO_KICKを出すステートマシン。
- library ieee;
- use ieee.std_logic_1164.all;
- use ieee.numeric_std.all;
- entity DELAY_SM is
- generic (
- G_COUNT : natural := 10
- );
- port (
- I_CLK : in std_logic;
- I_RST : in std_logic;
- I_KICK : in std_logic;
- O_KICK : out std_logic
- );
- end DELAY_SM;
- architecture rtl of DELAY_SM is
- type STATE is (IDLE, WAITFOR_FINISH);
- -- Verilog2005のclog2の代わり
- function clog2(value : integer) return integer is
- variable tmp : integer;
- variable result : integer;
- begin
- tmp := value - 1;
- result := 0;
- while tmp > 0 loop
- tmp := tmp/2;
- result := result + 1;
- end loop;
- return result;
- end clog2;
- signal current_st : STATE;
- signal next_st : STATE;
- signal start : std_logic;
- signal finish : std_logic;
- signal kick : std_logic;
- -- clog2(value)は、valueの「要素数」を表現できる最小限のビット幅を返す。
- -- valueまでの「値」を表現したいなら+1した値を与えなければならない。
- -- たとえば0~16までを表現したいなら、clog2(16+1)ビットが必要になる。
- signal count : unsigned(clog2(G_COUNT+1)-1 downto 0);
- begin
- -- ステートマシンの核はこれだけ。
- process (I_CLK, I_RST) begin
- if I_RST = '1' then
- current_st <= IDLE; -- リセットで初期状態へ遷移
- elsif I_CLK'event and I_CLK = '1' then
- current_st <= next_st;
- end if;
- end process;
- process (current_st, I_KICK, finish) begin
- start <= '0'; -- ここらへんには「なにも作用しない」ときの値を
- kick <= '0'; -- 列挙する。記述がもれるとラッチが生成される。
- case current_st is
- when IDLE =>
- if I_KICK = '1' then
- start <= '1'; -- こうするとミーリ型になる
- next_st <= WAITFOR_FINISH;
- else
- -- 遷移しない場合もnext_stへの代入を書く
- -- そうしないとラッチ生成
- next_st <= IDLE;
- end if;
- when WAITFOR_FINISH =>
- if finish = '1' then
- kick <= '1';
- next_st <= IDLE;
- else
- next_st <= WAITFOR_FINISH;
- end if;
- when others => -- othersでnext_stへの代入を忘れるとラッチ生成
- next_st <= IDLE;
- end case;
- end process;
- -- 組み合わせ出力からフリップフロップ出力に直す
- process (I_CLK, I_RST) begin
- if I_RST = '1' then
- O_KICK <= '0';
- elsif I_CLK'event and I_CLK = '1' then
- O_KICK <= kick;
- end if;
- end process;
- -- 値域は0~G_COUNT
- process (I_CLK, I_RST) begin
- if I_RST = '1' then
- count <= to_unsigned(0, count'length);
- elsif I_CLK'event and I_CLK = '1' then
- if start = '1' then
- count <= to_unsigned(1, count'length);
- elsif count = 0 then
- count <= count;
- elsif count < G_COUNT then
- count <= count + 1;
- else
- count <= count;
- end if;
- end if;
- end process;
- finish <= '1' when count = G_COUNT-1 else '0';
- end rtl;
[PageInfo]
LastUpdate: 2015-11-04 23:41:46, ModifiedBy: molelord
[License]
Creative Commons 2.1 Attribution
[Permissions]
view:all, edit:members, delete/config:members