FSMのためのテストベンチ / 自販機 / モジュラーテストベンチ
pp.551-555
- stimulus generatorが、投入される一連のコインに相当するトランザクションを生成する。
- ドライバーがコインを1個ずつDUVに与える。
- スコアボードがDUVの入出力をモニタリングする。
- スコアボード内部では、プレディクターがDUV出力の期待値を決定し、その値がコンパレーターによって実際の出力と照合される。
- ニッケルのシーケンスが"10000"、ダイムのシーケンスが"01000"の場合は、最初のクロックでニッケルが投入され、次のクロックでダイムが投入される。これが
driver
プロセスで実行される。 - 5クロックで2つの1ビット(ニッケルとダイム)を投入するので、全部で210とおりの組み合わせ全部を試す。
stimuli_generator
プロセスは、10ビット値"0000000000"~"1111111111"を生成して、前半5ビットと後半5ビットとをそれぞれニッケルのシーケンス、ダイムのシーケンスに割り振ることで、210とおりの組み合わせ全部を生成する。
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity vending_machine_fsm_tb is end; architecture testbench of vending_machine_fsm_tb is signal clock: std_logic := '0'; signal reset: std_logic := '0'; signal nickel_in: std_logic := '0'; signal dime_in: std_logic := '0'; signal dispense: std_logic; signal amount: std_logic_vector(3 downto 0); constant CLOCK_PERIOD: time := 20 ns; constant COMBINATIONAL_DELAY: time := 6 ns; type coins_transaction_type is record nickels: std_logic_vector(1 to 5); dimes: std_logic_vector(1 to 5); end record; signal transaction_data: coins_transaction_type; signal transaction_done: boolean; procedure wait_clock_edge is begin wait until rising_edge(clock); wait for COMBINATIONAL_DELAY; end; begin duv: entity work.vending_machine_fsm port map ( clock => clock, reset => reset, nickel_in => nickel_in, dime_in => dime_in, dispense => dispense, amount => amount ); clock <= not clock after CLOCK_PERIOD / 2; reset <= '1', '0' after 50 ns; stimuli_generator: process variable seq: std_logic_vector(1 to 10); begin wait until not reset; -- Generate all possible 10-bit sequences for i in 0 to 2**10-1 loop seq := std_logic_vector(to_unsigned(i, 10)); -- Break down each 10-bit sequence into sequences of nickels and dimes transaction_data <= ( nickels => seq(1 to 5), dimes => seq(6 to 10) ); wait on transaction_done'transaction; end loop; report "End of testbench. All tests completed successfully."; std.env.finish; end process; driver: process begin wait on transaction_data'transaction; for i in 1 to 5 loop nickel_in <= transaction_data.nickels(i); dime_in <= transaction_data.dimes(i); wait_clock_edge; end loop; transaction_done <= true; end process; response_checker: process variable amount_predicted, amount_duv: natural range 0 to 15; variable dispense_predicted: std_logic; begin wait_clock_edge; -- Predictor for the 'amount' output if reset = '1' or amount_predicted = 15 then amount_predicted := 0; elsif dime_in then amount_predicted := minimum(amount_predicted + 10, 15); elsif nickel_in then amount_predicted := amount_predicted + 5; end if; -- Predictor for the 'dispense' output amount_duv := to_integer(unsigned(testbench.amount)); dispense_predicted := '1' when amount_duv = 15 else '0'; -- Comparator - assert that DUV outputs and predictor outputs match assert amount_predicted = amount_duv report "amount IS NOT as expected: " & to_string(amount_duv) severity failure; assert dispense_predicted = dispense report "dispense IS NOT as expected: " & to_string(dispense) severity failure; end process; end;