From 6e3e7deb5eeceebf0a7fa7bb8ccc9f7a8fc68a8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20=C3=96rtenberg?= Date: Wed, 26 Feb 2025 17:57:03 +0100 Subject: [PATCH] At least i know what the problem is... --- src/socbridge_driver.vhd | 100 +++++++++------------------- src/socbridge_driver_tb.vhd | 90 +++++++++++++++++++------ src/socbridge_driver_tb_pkg.vhd | 112 ++++++++++++++++++++++++++++++++ 3 files changed, 212 insertions(+), 90 deletions(-) create mode 100644 src/socbridge_driver_tb_pkg.vhd diff --git a/src/socbridge_driver.vhd b/src/socbridge_driver.vhd index f0b9b77..3102ecf 100644 --- a/src/socbridge_driver.vhd +++ b/src/socbridge_driver.vhd @@ -1,13 +1,16 @@ library IEEE; use IEEE.std_logic_1164.all; +use IEEE.NUMERIC_STD.all; library work; use work.io_types.all; +use work.socbridge_driver_tb_pkg.all; entity socbridge_driver is port( clk : in std_logic; - rst : in std_logic; + rst : in std_logic; + cmd : in command_t; ext_in : in ext_socbridge_in_t; ext_out : out ext_socbridge_out_t; int_in : out int_socbridge_in_t; @@ -16,63 +19,8 @@ entity socbridge_driver is end entity socbridge_driver; architecture rtl of socbridge_driver is - type command_t is - (NO_OP, WRITE_ADD, WRITE, READ_ADD, READ, P_ERR); - - type response_t is - (NO_OP, WRITE_ACK, READ_RESPONSE); - - type state_t is - (RESET, IDLE, TX_HEADER, TX_BODY, TX_ACK, RX_HEADER, RX_RESPONSE, RX_BODY); - - type ext_protocol_t is record - data : std_logic_vector(interface_inst.socbridge.payload_width - 1 downto 0); - clk : std_logic; - parity : std_logic; - end record ext_protocol_t; - - type state_rec_t is record - curr_state: state_t; - ext_in_reg, ext_out_reg : ext_protocol_t; - end record state_rec_t; - - pure function calc_parity( - d : STD_LOGIC_VECTOR(interface_inst.socbridge.payload_width - 1 downto 0) - ) return std_logic is - variable parity : std_logic; - begin - parity := d(0); - for x in 1 to d'length - 1 loop - parity := parity xor d(x); - end loop; - return not parity; - end function; - - pure function create_ext_protocol_from_io_type_in( - input : ext_socbridge_in_t - ) return ext_protocol_t is - variable val : ext_protocol_t; - begin - val.data := input.payload; - val.clk := input.control(1); - val.parity := input.control(0); - return val; - end function; - pure function create_io_type_out_from_ext_protocol( - input : ext_protocol_t - ) return ext_socbridge_out_t is - variable val : ext_socbridge_out_t; - begin - val.payload:= input.data; - val.control(1) := input.clk; - val.control(0) := input.parity; - return val; - end function; signal next_parity_out : std_logic; - - - signal ext_in_rec : ext_protocol_t; signal ext_out_data_cmd : std_logic_vector(interface_inst.socbridge.payload_width - 1 downto 0); signal next_state : state_t; @@ -82,6 +30,22 @@ architecture rtl of socbridge_driver is signal curr_response_bits : std_logic_vector(4 downto 0); signal st : state_rec_t; begin + next_parity_out <= calc_parity(ext_out_data_cmd); + --- DEBUG GLOBAL BINDINGS --- + -- synthesis translate_off + G_next_parity_out <= next_parity_out; + G_ext_in_rec <= ext_in_rec; + G_ext_out_data_cmd <= ext_out_data_cmd; + G_next_state <= next_state; + G_curr_command <= curr_command; + G_curr_command_bits <= curr_command_bits; + G_curr_respoonse <= curr_respoonse; + G_curr_response_bits <= curr_response_bits; + G_st <= st; + -- synthesis translate_on + + + comb_proc: process(ext_in, int_out, st) begin -- Outputs @@ -91,15 +55,6 @@ begin -- Helpful Bindings -- ext_in_rec <= create_ext_protocol_from_io_type_in(ext_in); curr_response_bits <= ext_in_rec.data(7 downto 3); - next_parity_out <= calc_parity(ext_out_data_cmd); - with curr_command select - curr_command_bits <= "00000" when NO_OP, - "10000" when WRITE_ADD, - "10100" when WRITE, - "11000" when READ_ADD, - "11100" when READ, - "01001" when P_ERR, - "11111" when others; with curr_response_bits select curr_respoonse <= WRITE_ACK when "00001", WRITE_ACK when "00101", @@ -135,9 +90,9 @@ begin --- Next State Assignment --- case st.curr_state is when IDLE => - if curr_command = WRITE or curr_command = WRITE_ADD then + if cmd = WRITE or cmd = WRITE_ADD then next_state <= TX_HEADER; - elsif curr_command = READ or curr_command = READ_ADD then + elsif cmd = READ or cmd = READ_ADD then next_state <= RX_HEADER; else next_state <= IDLE; @@ -185,7 +140,7 @@ begin when RESET => when TX_HEADER => curr_command <= WRITE; - ext_out_data_cmd <= curr_command_bits & "001"; + ext_out_data_cmd <= get_command_bits(WRITE) & "001"; when TX_BODY => ext_out_data_cmd <= int_out.payload; int_in.is_full_out <= '0'; @@ -196,7 +151,8 @@ begin when RX_RESPONSE => when RX_BODY => end case; - + report "Running comb part with ext_out_data_cmd = " & to_string(ext_out_data_cmd) severity note; + report "Running comb part with next_parity_out = " & std_logic'image(next_parity_out) severity note; end process comb_proc; -- Process updating internal registers based on primary clock seq_proc: process(ext_in_rec.clk, rst) @@ -209,12 +165,14 @@ begin st.curr_state <= IDLE; elsif(rising_edge(ext_in_rec.clk)) then + report "Running seq part with ext_out_data_cmd = " & to_string(ext_out_data_cmd) severity note; + report "Running seq part with next_parity_out = " & std_logic'image(next_parity_out) severity note; + st.ext_out_reg.parity <= next_parity_out; st.ext_in_reg.data <= ext_in_rec.data; st.ext_in_reg.clk <= ext_in_rec.clk; st.ext_in_reg.parity <= ext_in_rec.parity; - st.ext_out_reg.data <= int_out.payload; + st.ext_out_reg.data <= ext_out_data_cmd; st.ext_out_reg.clk <= not st.ext_out_reg.clk; - st.ext_out_reg.parity <= next_parity_out; st.curr_state <= next_state; end if; end process seq_proc; diff --git a/src/socbridge_driver_tb.vhd b/src/socbridge_driver_tb.vhd index 17dc5d1..9b009e1 100644 --- a/src/socbridge_driver_tb.vhd +++ b/src/socbridge_driver_tb.vhd @@ -3,29 +3,31 @@ use IEEE.std_logic_1164.all; use IEEE.MATH_REAL.all; library work; use work.io_types.all; +use work.socbridge_driver_tb_pkg.all; entity socbridge_driver_tb is end entity socbridge_driver_tb; architecture tb of socbridge_driver_tb is - pure function calc_parity( - d : STD_LOGIC_VECTOR(interface_inst.socbridge.payload_width - 1 downto 0) - ) return std_logic is - variable parity : std_logic; + impure function check_next_state(correct_state: state_t) return boolean is begin - parity := d(0); - for x in 1 to d'length - 1 loop - parity := parity xor d(x); - end loop; - return not parity; + 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; + return FALSE; + end if; + return TRUE; end function; + + component socbridge_driver is port( clk : in std_logic; - rst : in std_logic; + rst : in std_logic; + cmd : in command_t; ext_in : in ext_socbridge_in_t; ext_out : out ext_socbridge_out_t; int_in : out int_socbridge_in_t; @@ -34,6 +36,7 @@ architecture tb of socbridge_driver_tb is end component socbridge_driver; signal clk : std_logic := '0'; signal rst : std_logic; + signal cmd : command_t; signal ext_in : ext_socbridge_in_t; signal ext_out : ext_socbridge_out_t; signal int_in : int_socbridge_in_t; @@ -45,12 +48,11 @@ architecture tb of socbridge_driver_tb is constant SIMULATION_CYCLE_COUNT : INTEGER := 100; begin - - socbridge_driver_inst: entity work.socbridge_driver port map( clk => clk, rst => rst, + cmd => cmd, ext_in => ext_in, ext_out => ext_out, int_in => int_in, @@ -74,7 +76,7 @@ begin wait for CLK_PERIOD / 2; for x in 0 to SIMULATION_CYCLE_COUNT loop if last_clk = ext_out.control(1) then - report "Secondary side clk not correct." severity warning; + report "Secondary side clk not correct." severity error; end if; last_clk := ext_out.control(1); wait for CLK_PERIOD; @@ -85,16 +87,61 @@ begin verify_parity: process variable curr_parity : std_logic; begin - for x in 0 to SIMULATION_CYCLE_COUNT * 2 loop + for x in 0 to SIMULATION_CYCLE_COUNT * 10 loop curr_parity := calc_parity(ext_out.payload); if not (curr_parity = ext_out.control(0)) then - report "Secondary side parity not correct" severity warning; + report "Secondary side parity not correct" severity error; + wait for CLK_PERIOD; + report "Ending Simulation... " severity FAILURE; end if; - wait for CLK_PERIOD / 2; + wait for CLK_PERIOD / 10; end loop; wait; end process verify_parity; + verify_next_state : process + variable nsv: boolean; + begin + wait for 3 * CLK_PERIOD; + wait for CLK_PERIOD / 2; + nsv := check_next_state(IDLE); + wait for CLK_PERIOD; + nsv := check_next_state(TX_HEADER); + wait for CLK_PERIOD; + nsv := check_next_state(TX_BODY); + wait for CLK_PERIOD; + nsv := check_next_state(TX_ACK); + wait for CLK_PERIOD; + nsv := check_next_state(TX_ACK); + wait for CLK_PERIOD; + nsv := check_next_state(IDLE); + wait for CLK_PERIOD; + nsv := check_next_state(IDLE); + wait for CLK_PERIOD; + nsv := check_next_state(IDLE); + wait for CLK_PERIOD; + nsv := check_next_state(IDLE); + wait for CLK_PERIOD; + nsv := check_next_state(IDLE); + wait for CLK_PERIOD; + nsv := check_next_state(IDLE); + wait for CLK_PERIOD; + nsv := check_next_state(IDLE); + wait for CLK_PERIOD; + wait; + end process verify_next_state; + + command_stimulus: process + begin + cmd <= NO_OP; + wait for 3*CLK_PERIOD; + wait for CLK_PERIOD / 2; + cmd <= WRITE; + wait for CLK_PERIOD; + cmd <= NO_OP; + wait; + end process command_stimulus; + external_stimulus_signal: process(curr_word) begin ext_in.payload <= curr_word; @@ -108,12 +155,11 @@ begin wait for 3 * CLK_PERIOD; rst <= '0'; wait for CLK_PERIOD / 2; - -- stimulus goes here - wait for CLK_PERIOD*10; + wait for 3* CLK_PERIOD; + curr_word <= "00001001"; wait; end process external_stimulus; - internal_stimulus: process begin int_out.is_full_in <= '0'; @@ -123,16 +169,22 @@ begin int_out.write_enable_out <= '1'; int_out.payload <= "00000000"; wait until int_in.is_full_out = '0'; + wait until rising_edge(clk); int_out.payload <= "00000010"; wait until int_in.is_full_out = '0'; + wait until rising_edge(clk); int_out.payload <= "00000100"; wait until int_in.is_full_out = '0'; + wait until rising_edge(clk); int_out.payload <= "00001000"; wait until int_in.is_full_out = '0'; + wait until rising_edge(clk); int_out.payload <= "00010000"; wait until int_in.is_full_out = '0'; + wait until rising_edge(clk); int_out.payload <= "00100000"; wait until int_in.is_full_out = '0'; + wait until rising_edge(clk); wait; end process internal_stimulus; diff --git a/src/socbridge_driver_tb_pkg.vhd b/src/socbridge_driver_tb_pkg.vhd new file mode 100644 index 0000000..676b6ef --- /dev/null +++ b/src/socbridge_driver_tb_pkg.vhd @@ -0,0 +1,112 @@ +library IEEE; +use IEEE.std_logic_1164.all; +library work; +use work.io_types.all; + + +package socbridge_driver_tb_pkg is + type command_t is + (NO_OP, WRITE_ADD, WRITE, READ_ADD, READ, P_ERR); + + type response_t is + (NO_OP, WRITE_ACK, READ_RESPONSE); + + type state_t is + (RESET, IDLE, TX_HEADER, TX_BODY, TX_ACK, RX_HEADER, RX_RESPONSE, RX_BODY); + + type ext_protocol_t is record + data : std_logic_vector(interface_inst.socbridge.payload_width - 1 downto 0); + clk : std_logic; + parity : std_logic; + end record ext_protocol_t; + + type state_rec_t is record + curr_state: state_t; + ext_in_reg, ext_out_reg : ext_protocol_t; + end record state_rec_t; + impure function calc_parity( + d : STD_LOGIC_VECTOR(interface_inst.socbridge.payload_width - 1 downto 0) + ) return std_logic; + pure function create_ext_protocol_from_io_type_in ( + input : ext_socbridge_in_t + ) return ext_protocol_t; + pure function create_io_type_out_from_ext_protocol( + input: ext_protocol_t + ) return ext_socbridge_out_t; + function to_string ( a: std_logic_vector) return string; + pure function get_command_bits(command : command_t) return std_logic_vector; + --- DEBUG GLOBAL SIGNALS --- + -- synthesis translate_off + signal G_next_parity_out : std_logic; + signal G_ext_in_rec : ext_protocol_t; + signal G_ext_out_data_cmd : std_logic_vector(interface_inst.socbridge.payload_width - 1 downto 0); + signal G_next_state : state_t; + signal G_curr_command : command_t; + signal G_curr_command_bits : std_logic_vector(4 downto 0); + signal G_curr_respoonse : response_t; + signal G_curr_response_bits : std_logic_vector(4 downto 0); + signal G_st : state_rec_t; + -- synthesis translate_on + +end package socbridge_driver_tb_pkg; + +package body socbridge_driver_tb_pkg is + function to_string ( a: std_logic_vector) return string is + variable b : string (1 to a'length) := (others => NUL); + variable stri : integer := 1; + begin + for i in a'range loop + b(stri) := std_logic'image(a((i)))(2); + stri := stri+1; + end loop; + return b; + end function; + + impure function calc_parity( + d : STD_LOGIC_VECTOR(interface_inst.socbridge.payload_width - 1 downto 0) + ) return std_logic is + variable parity : std_logic; + begin + parity := d(0); + for x in integer'(1) to d'length - 1 loop + parity := parity xor d(x); + end loop; + return not parity; + end function; + + pure function create_ext_protocol_from_io_type_in( + input : ext_socbridge_in_t + ) return ext_protocol_t is + variable val : ext_protocol_t; + begin + val.data := input.payload; + val.clk := input.control(1); + val.parity := input.control(0); + return val; + end function; + pure function create_io_type_out_from_ext_protocol( + input : ext_protocol_t + ) return ext_socbridge_out_t is + variable val : ext_socbridge_out_t; + begin + val.payload:= input.data; + val.control(1) := input.clk; + val.control(0) := input.parity; + return val; + end function; + pure function get_command_bits(command : command_t) + return std_logic_vector is + variable val : std_logic_vector(4 downto 0); + begin + with command select + val := "00000" when NO_OP, + "10000" when WRITE_ADD, + "10100" when WRITE, + "11000" when READ_ADD, + "11100" when READ, + "01001" when P_ERR, + "11111" when others; + return val; + end function; + +end package body socbridge_driver_tb_pkg;