274 lines
11 KiB
VHDL
274 lines
11 KiB
VHDL
library IEEE;
|
|
use IEEE.std_logic_1164.all;
|
|
use IEEE.NUMERIC_STD.all;
|
|
library ganimede;
|
|
use ganimede.io_types.all;
|
|
library socbridge;
|
|
use socbridge.socbridge_driver_tb_pkg.all;
|
|
library controller;
|
|
|
|
entity control_socbridge_tb is
|
|
end entity control_socbridge_tb;
|
|
|
|
architecture tb of control_socbridge_tb is
|
|
|
|
constant CLK_PERIOD : Time := 10 ns;
|
|
constant SIMULATION_CYCLE_COUNT : integer := 200;
|
|
signal clk, rst : std_logic := '0';
|
|
signal cu_to_sb_cmd: command_t;
|
|
signal cu_to_sb_address: std_logic_vector(31 downto 0);
|
|
signal cmd_size : positive;
|
|
signal ext_socbridge_in : ext_socbridge_in_t := (
|
|
payload => (others => '0'),
|
|
control => (others => '0')
|
|
);
|
|
signal ext_socbridge_out : ext_socbridge_out_t;
|
|
signal int_socbridge_out : int_socbridge_out_t;
|
|
signal int_socbridge_in : int_socbridge_in_t := (
|
|
payload => (others => '0'),
|
|
write_enable_out => '0',
|
|
is_full_in => '0'
|
|
);
|
|
signal ext_control_input: ext_control_unit_in_t := (
|
|
driver_id => (others => '0'),
|
|
address => (others => '0'),
|
|
seq_mem_access_count => 0,
|
|
cmd => "00"
|
|
);
|
|
signal int_control_input: int_control_unit_in_t := (active_driver => (others => '0'));
|
|
signal ext_control_output: ext_control_unit_out_t;
|
|
signal int_control_output: int_control_unit_out_t;
|
|
|
|
signal driver_to_control: driver_to_control_t;
|
|
signal control_to_driver: control_to_driver_t;
|
|
|
|
signal curr_word : std_logic_vector(ext_socbridge_in.payload'length - 1 downto 0);
|
|
signal expected_out : std_logic_vector(ext_socbridge_out.payload'length - 1 downto 0);
|
|
|
|
procedure fail(error_msg : string) is
|
|
begin
|
|
wait for CLK_PERIOD;
|
|
report "Simulation ending due to: " & error_msg & ". Shutting down..." severity FAILURE;
|
|
end procedure;
|
|
|
|
procedure check_next_state(correct_state: state_t) is
|
|
begin
|
|
if(not (correct_state = G_next_state)) then
|
|
report "Next State is not what was expected, found " & state_t'image(G_next_state)
|
|
& " but expected " & state_t'image(correct_state) severity error;
|
|
fail("Next State");
|
|
end if;
|
|
end procedure;
|
|
|
|
procedure check_data_out(correct_data: std_logic_vector(ext_socbridge_out.payload'length - 1 downto 0)) is
|
|
begin
|
|
if(not (correct_data = ext_socbridge_out.payload)) then
|
|
report "Data out is not what was expected, found " & to_string(ext_socbridge_out.payload)
|
|
& " but expected " & to_string(correct_data) severity error;
|
|
fail("Data out");
|
|
end if;
|
|
end procedure;
|
|
|
|
procedure check_parity(correct_data: std_logic_vector(ext_socbridge_out.payload'length - 1 downto 0)) is
|
|
begin
|
|
if(not (calc_parity(correct_data) = calc_parity(ext_socbridge_out.payload))) then
|
|
report "Parity out is not what was expected, found " & std_logic'image(calc_parity(ext_socbridge_out.payload))
|
|
& " but expected " & std_logic'image(calc_parity(correct_data)) severity error;
|
|
fail("Parity out");
|
|
end if;
|
|
end procedure;
|
|
|
|
begin
|
|
socbridge_inst: entity socbridge.socbridge_driver
|
|
port map(
|
|
clk => clk,
|
|
rst => rst,
|
|
ctrl_in => control_to_driver,
|
|
ctrl_out => driver_to_control,
|
|
ext_in => ext_socbridge_in,
|
|
ext_out => ext_socbridge_out,
|
|
int_in => int_socbridge_in,
|
|
int_out => int_socbridge_out
|
|
);
|
|
|
|
control_unit_inst: entity controller.control_unit
|
|
port map(
|
|
clk => clk,
|
|
rst => rst,
|
|
ext_control_in => ext_control_input,
|
|
ext_control_out => ext_control_output,
|
|
int_control_in => int_control_input,
|
|
int_control_out => int_control_output
|
|
);
|
|
|
|
control_to_driver.address <= int_control_output.address;
|
|
control_to_driver.request <= int_control_output.driver_id(0);
|
|
control_to_driver.instruction <= int_control_output.instruction;
|
|
control_to_driver.seq_mem_access_count <= int_control_output.seq_mem_access_count;
|
|
|
|
int_control_input.active_driver(0) <= driver_to_control.is_active;
|
|
|
|
ext_socbridge_in.control(1) <= clk;
|
|
control_clock_proc: process
|
|
begin
|
|
for i in 0 to SIMULATION_CYCLE_COUNT - 1 loop
|
|
wait for CLK_PERIOD / 2;
|
|
clk <= not clk;
|
|
end loop;
|
|
wait;
|
|
end process control_clock_proc;
|
|
|
|
stimulus_proc: process
|
|
begin
|
|
report "Starting Simulation Stimulus!";
|
|
rst <= '1';
|
|
ext_control_input.address <= (others => '0');
|
|
ext_control_input.cmd <= "00";
|
|
ext_control_input.driver_id <= "1";
|
|
ext_control_input.seq_mem_access_count <= 2;
|
|
wait for 3 * CLK_PERIOD;
|
|
report "Reset grace period ended, starting stimulus...";
|
|
rst <= '0';
|
|
ext_control_input.address <= x"FA0FA0FA";
|
|
ext_control_input.cmd <= "01";
|
|
wait until int_control_input.active_driver(0) = '1';
|
|
report "Task received in driver, awaiting completion...";
|
|
ext_control_input.address <= (others => '0');
|
|
ext_control_input.cmd <= "00";
|
|
wait until int_control_input.active_driver(0) = '0';
|
|
wait for CLK_PERIOD;
|
|
report "Task completed in driver, sending next task...";
|
|
ext_control_input.address <= x"FA0FA0FA";
|
|
ext_control_input.cmd <= "10";
|
|
wait for CLK_PERIOD;
|
|
wait until int_control_input.active_driver(0) = '1';
|
|
report "Task received in driver, awaiting completion...";
|
|
ext_control_input.address <= (others => '0');
|
|
ext_control_input.cmd <= "00";
|
|
wait until int_control_input.active_driver(0) = '0';
|
|
wait for CLK_PERIOD;
|
|
report "Task completed in driver, ending simulation stimulus";
|
|
|
|
wait;
|
|
end process stimulus_proc;
|
|
|
|
external_stimulus_signal: process(curr_word)
|
|
begin
|
|
ext_socbridge_in.payload <= curr_word;
|
|
ext_socbridge_in.control(0) <= calc_parity(curr_word);
|
|
end process external_stimulus_signal;
|
|
|
|
external_stimulus: process
|
|
begin
|
|
wait for CLK_PERIOD / 1000;
|
|
curr_word <= "00000000";
|
|
wait for 999 * CLK_PERIOD / 1000;
|
|
wait for 2 * CLK_PERIOD;
|
|
wait for CLK_PERIOD / 2;
|
|
wait for 10* CLK_PERIOD;
|
|
curr_word <= "00001001";
|
|
wait for CLK_PERIOD;
|
|
curr_word <= "00000000";
|
|
wait for CLK_PERIOD * 20;
|
|
curr_word <= "00101001";
|
|
wait for CLK_PERIOD;
|
|
curr_word <= "00000000";
|
|
wait for CLK_PERIOD*10;
|
|
curr_word <= "01100001";
|
|
wait for CLK_PERIOD;
|
|
curr_word <= "00100000";
|
|
wait for CLK_PERIOD;
|
|
curr_word <= "00010000";
|
|
wait for CLK_PERIOD;
|
|
curr_word <= "00000000";
|
|
|
|
|
|
wait;
|
|
end process external_stimulus;
|
|
|
|
internal_stimulus: process
|
|
variable input : positive := 1;
|
|
begin
|
|
int_socbridge_in.is_full_in <= '0';
|
|
int_socbridge_in.write_enable_out <= '0';
|
|
wait for 3 * CLK_PERIOD;
|
|
-- stimulus goes here
|
|
int_socbridge_in.write_enable_out <= '1';
|
|
int_socbridge_in.payload <= std_logic_vector(to_unsigned(input, int_socbridge_in.payload'length));
|
|
input := input + 1 mod 256;
|
|
wait until rising_edge(clk) and int_socbridge_out.is_full_out = '0';
|
|
int_socbridge_in.write_enable_out <= '1';
|
|
int_socbridge_in.payload <= std_logic_vector(to_unsigned(input, int_socbridge_in.payload'length));
|
|
input := input + 1 mod 256;
|
|
wait until rising_edge(clk) and int_socbridge_out.is_full_out = '0';
|
|
wait until falling_edge(clk);
|
|
int_socbridge_in.write_enable_out <= '1';
|
|
int_socbridge_in.payload <= std_logic_vector(to_unsigned(input, int_socbridge_in.payload'length));
|
|
input := input + 1 mod 256;
|
|
wait until rising_edge(clk) and int_socbridge_out.is_full_out = '0';
|
|
wait until falling_edge(clk);
|
|
int_socbridge_in.write_enable_out <= '1';
|
|
int_socbridge_in.payload <= std_logic_vector(to_unsigned(input, int_socbridge_in.payload'length));
|
|
input := input + 1 mod 256;
|
|
wait until rising_edge(clk) and int_socbridge_out.is_full_out = '0';
|
|
wait until falling_edge(clk);
|
|
int_socbridge_in.write_enable_out <= '1';
|
|
int_socbridge_in.payload <= std_logic_vector(to_unsigned(input, int_socbridge_in.payload'length));
|
|
input := input + 1 mod 256;
|
|
wait until rising_edge(clk) and int_socbridge_out.is_full_out = '0';
|
|
wait until falling_edge(clk);
|
|
int_socbridge_in.write_enable_out <= '1';
|
|
int_socbridge_in.payload <= std_logic_vector(to_unsigned(input, int_socbridge_in.payload'length));
|
|
input := input + 1 mod 256;
|
|
wait until rising_edge(clk) and int_socbridge_out.is_full_out = '0';
|
|
wait until falling_edge(clk);
|
|
int_socbridge_in.write_enable_out <= '1';
|
|
int_socbridge_in.payload <= std_logic_vector(to_unsigned(input, int_socbridge_in.payload'length));
|
|
input := input + 1 mod 256;
|
|
wait until rising_edge(clk) and int_socbridge_out.is_full_out = '0';
|
|
wait until falling_edge(clk);
|
|
int_socbridge_in.write_enable_out <= '1';
|
|
int_socbridge_in.payload <= std_logic_vector(to_unsigned(input, int_socbridge_in.payload'length));
|
|
input := input + 1 mod 256;
|
|
wait until rising_edge(clk) and int_socbridge_out.is_full_out = '0';
|
|
wait until falling_edge(clk);
|
|
int_socbridge_in.write_enable_out <= '1';
|
|
int_socbridge_in.payload <= std_logic_vector(to_unsigned(input, int_socbridge_in.payload'length));
|
|
input := input + 1 mod 256;
|
|
wait until rising_edge(clk) and int_socbridge_out.is_full_out = '0';
|
|
wait until falling_edge(clk);
|
|
int_socbridge_in.write_enable_out <= '1';
|
|
int_socbridge_in.payload <= std_logic_vector(to_unsigned(input, int_socbridge_in.payload'length));
|
|
input := input + 1 mod 256;
|
|
wait until rising_edge(clk) and int_socbridge_out.is_full_out = '0';
|
|
wait until falling_edge(clk);
|
|
int_socbridge_in.write_enable_out <= '1';
|
|
int_socbridge_in.payload <= std_logic_vector(to_unsigned(input, int_socbridge_in.payload'length));
|
|
input := input + 1 mod 256;
|
|
wait until rising_edge(clk) and int_socbridge_out.is_full_out = '0';
|
|
wait until falling_edge(clk);
|
|
int_socbridge_in.write_enable_out <= '1';
|
|
int_socbridge_in.payload <= std_logic_vector(to_unsigned(input, int_socbridge_in.payload'length));
|
|
input := input + 1 mod 256;
|
|
wait until rising_edge(clk) and int_socbridge_out.is_full_out = '0';
|
|
wait until falling_edge(clk);
|
|
int_socbridge_in.write_enable_out <= '1';
|
|
int_socbridge_in.payload <= std_logic_vector(to_unsigned(input, int_socbridge_in.payload'length));
|
|
input := input + 1 mod 256;
|
|
wait until rising_edge(clk) and int_socbridge_out.is_full_out = '0';
|
|
wait until falling_edge(clk);
|
|
int_socbridge_in.write_enable_out <= '1';
|
|
int_socbridge_in.payload <= std_logic_vector(to_unsigned(input, int_socbridge_in.payload'length));
|
|
input := input + 1 mod 256;
|
|
wait until rising_edge(clk) and int_socbridge_out.is_full_out = '0';
|
|
wait until falling_edge(clk);
|
|
int_socbridge_in.write_enable_out <= '1';
|
|
int_socbridge_in.payload <= std_logic_vector(to_unsigned(input, int_socbridge_in.payload'length));
|
|
input := input + 1 mod 256;
|
|
wait until rising_edge(clk) and int_socbridge_out.is_full_out = '0';
|
|
wait until falling_edge(clk);
|
|
wait;
|
|
end process internal_stimulus;
|
|
|
|
end architecture tb;
|