前回はChatGPTに10進カウンターをVHDLで書いてもらいました。今回は汎用のロジックICであるSN74HC595をVHDLで設計してもらいます。
SN74HC595はテキサスインスツルメンツが提供する8ビットシフトレジスタであり、出力レジスタにパラレルに入力をシフトすることができます。シリアルデータ入力と8つのパラレル出力ピンを持ち、内部レジスタにデータを蓄積している間に、出力ピンを介して前の転送の結果を保持します。SN74HC595は、マイクロコントローラやマイクロプロセッサとのインターフェースで使用され、LEDドライバーやディスプレイなどのアプリケーションで広く使用されています。
74HC595の回路とテストベンチをVHDLで
ざっくりと「74HC595の回路とテストベンチをVHDLで設計して」と頼んだら以下のコードを出力しました(テストベンチは省略)。
library IEEE; use IEEE.std_logic_1164.all; entity sn74hc595 is port ( clk: in std_logic; -- クロック信号 srclr: in std_logic; -- シフトレジスタクリア信号 oe: in std_logic; -- 出力イネーブル信号 ser: in std_logic; -- シリアルデータ入力信号 srclk: in std_logic; -- シフトレジスタクロック信号 rclk: in std_logic; -- レジスタクロック信号 q: out std_logic_vector(7 downto 0) -- パラレル出力信号 ); end sn74hc595; architecture behavioral of sn74hc595 is signal shift_reg: std_logic_vector(7 downto 0); begin process (clk) begin if rising_edge(clk) then if srclr = '1' then -- シフトレジスタクリア信号がアサートされた場合 shift_reg <= (others => '0'); -- シフトレジスタをクリアする elsif oe = '0' then -- 出力イネーブルがアサートされた場合 q <= shift_reg; -- パラレル出力にシフトレジスタの内容を反映する elsif rising_edge(srclk) then -- シフトレジスタクロックの立ち上がりエッジ shift_reg <= ser & shift_reg(7 downto 1); -- シフトレジスタにシリアルデータを入力する elsif rising_edge(rclk) then -- レジスタクロックの立ち上がりエッジ q <= shift_reg; -- パラレル出力にシフトレジスタの内容を反映する end if; end if; end process; end behavioral;
そもそも、74HC595はクロック信号としてシフトクロック(srclk)とストレージレジスタのラッチクロック(rclk)の2つですが、もう一つのクロック(clk)があります。また、このコードはQuartus Primeでは動きません。
仕様を明確にして
そこで、入力信号は74HC595と同じになるように指定し、コンパイラも何を使うかを指定しました。こんな感じです。
「SN74HC595の回路をハードウェア記述言語のVHDLで設計し記述はrtlで。また、quartus primeでコンパイルできるようにして。
入力信号はsrclk:シフトクロック、srclr:シフトレジスタクリア、oe:出力イネーブル、rclk:パラレルデータラッチクロック、ser:シリアルデータ入力信号として出力信号はq:パラレル出力信号とする。
テストベンチはシリアルデータ”01011010″を入力してその出力を確認するような記述として。」
そこ結果が以下です。
library ieee; use ieee.std_logic_1164.all; entity SN74HC595 is port ( srclk : in std_logic; srclr : in std_logic; oe : in std_logic; rclk : in std_logic; ser : in std_logic; q : out std_logic_vector(7 downto 0) ); end entity; architecture rtl of SN74HC595 is signal shift_reg : std_logic_vector(7 downto 0) := (others => '0'); begin process (srclk, srclr) begin if srclr = '1' then shift_reg <= (others => '0'); elsif rising_edge(srclk) then shift_reg <= ser & shift_reg(7 downto 1); end if; end process; process (rclk) begin if rising_edge(rclk) then if oe = '1' then q <= shift_reg; else q <= (others => 'Z'); end if; end if; end process; end architecture;
想定していたコードを出力してくれました。
テストベンチは以下です。
library ieee; use ieee.std_logic_1164.all; entity testbench is end entity; architecture sim of testbench is signal srclk, srclr, oe, rclk, ser : std_logic; signal q : std_logic_vector(7 downto 0); begin uut : entity work.SN74LS595A port map ( srclk => srclk, srclr => srclr, oe => oe, rclk => rclk, ser => ser, q => q ); stimulus : process begin ser <= '0'; srclr <= '1'; srclk <= '0'; oe <= '1'; rclk <= '0'; wait for 10 ns; srclr <= '0'; wait for 10 ns; for i in 0 to 7 loop ser <= "01011010"(i); srclk <= '1'; wait for 10 ns; srclk <= '0'; wait for 10 ns; end loop; rclk <= '1'; wait for 10 ns; rclk <= '0'; wait for 10 ns; assert q = "01011010" report "Output is incorrect" severity error; wait; end process; end architecture;
Process文のループでserにデータを入力している箇所がおかしそうです。実際、このテストベンチをコンパイルするとエラーが出ます。
そこで、ChatGPTが書いたコードとQuartusが吐き出したエラー内容をコピペして知らせると、ChatGPT自身の書いたコードのおかしなところを指摘して修正したコードを出力しました。
何度か同じようにした結果が以下のコードです。
library ieee; use ieee.std_logic_1164.all; entity testbench is end entity; architecture sim of testbench is signal srclk, srclr, oe, rclk, ser : std_logic; signal q : std_logic_vector(7 downto 0); signal serial_in : std_logic_vector(7 downto 0); begin uut : entity work.SN74LV595A port map ( srclk => srclk, srclr => srclr, oe => oe, rclk => rclk, ser => ser, q => q ); stimulus : process begin serial_in <= "01011010"; ser <= '0'; srclr <= '1'; srclk <= '0'; oe <= '1'; rclk <= '0'; wait for 10 ns; srclr <= '0'; wait for 10 ns; for i in 0 to 7 loop ser <= serial_in(i); srclk <= '1'; wait for 10 ns; srclk <= '0'; wait for 10 ns; end loop; rclk <= '1'; wait for 10 ns; rclk <= '0'; wait for 10 ns; assert q = "01011010" report "Output is incorrect" severity error; wait; end process; end architecture;
エラーの出なくなったテストベンチでシミュレーションしたのが以下です。
と言うことで
と言うことで、エラーの内容を知らせてあげたり対話をしながらですがChatGPTが回路とテストベンチを書いてくれました。また、人間も同じですが仕様を明確にして伝えてあげることが大事ですね。