I'm attempting to write a I2C bus master in VHDL - and thoroughly test it to ensure it works etc. In doing so, I've written the module and a subsequent test-bench to test it under different stimuli - namely changing addresses and data input after each sending cycle (which is when the busy goes low).
To do this, I first attempted to increment the value in the data bus and decrement the values in the address bus, using the techniques described in this question here. However, when I did this, rather than the address bus taking the new value, it takes an uninitialised value and the assignment statement doesnt seem to execute.
I then attempted to use an intermediate integer signal, however this produced the same results, however this means that the address & data buses take the correct value for the first cycle - but then don't increment and instead take a unknown state!
Ultimately my question is why do these errors occur - and how do I fix/avoid them?
My code for the I2C master module can be found here and the code for the I2CBus (testbench) can be found here. Any other information I can provide to help please just say!
Thanks very much,
David
-----Code using intermediate signals------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY I2CBus IS
END I2CBus;
ARCHITECTURE behavior OF I2CBus IS
COMPONENT IIC_Master
PORT(
CLOCK : IN std_logic;
RESET_N : IN std_logic;
ENA : IN std_logic;
ADR : IN std_logic_vector(6 downto 0);
RW : IN std_logic;
DAT_WR : IN std_logic_vector(7 downto 0);
DAT_RD : OUT std_logic_vector(7 downto 0);
BUSY : OUT std_logic;
SCL : INOUT std_logic;
SDA : INOUT std_logic;
ACK_ERR : BUFFER std_logic
);
END COMPONENT;
--Inputs
signal CLOCK : std_logic := '0';
signal RESET_N : std_logic; --active high
signal ENA : std_logic; --active high
signal ADR : std_logic_vector(6 downto 0);
signal RW : std_logic; --read high write low
signal DAT_WR : std_logic_vector(7 downto 0);
--BiDirs
signal SCL : std_logic;
signal SDA : std_logic;
--Outputs
signal DAT_RD : std_logic_vector(7 downto 0);
signal BUSY : std_logic;
signal ACK_ERR : std_logic;
-- Clock period definitions
constant CLOCK_period : time := 5 ns;
--Signals to vary
signal address : integer := 127;
signal input_data : integer := 0;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut : IIC_Master PORT MAP(
CLOCK => CLOCK,
RESET_N => RESET_N,
ENA => ENA,
ADR => ADR,
RW => RW,
DAT_WR => DAT_WR,
DAT_RD => DAT_RD,
BUSY => BUSY,
SCL => SCL,
SDA => SDA,
ACK_ERR => ACK_ERR
);
-- Clock process definitions
CLOCK_process : process
begin
CLOCK <= '0';
wait for CLOCK_period / 2;
CLOCK <= '1';
wait for CLOCK_period / 2;
end process;
-- Reset process
reset : process
begin
reset_n <= '0';
ADR <= "1111111"; --This doesn't seem to happen the first time?
DAT_WR <= "00000000"; --Nor does this?
RW <= '0';
wait for 50 ns;
reset_n <= '1';
ENA <= '1';
wait;
end process;
stim_proc : process
begin
DAT_WR <= std_logic_vector(to_unsigned(input_data, 8));
ADR <= std_logic_vector(to_unsigned(address, 7));
if input_data < 127 then
address <= address - 1;
input_data <= input_data + 1;
wait until BUSY = '0' and RESET_N = '1';
elsif unsigned(DAT_WR) > 126 then
wait;
end if;
end process;
end behavior;
------1st Stimulus Process w/out intermediate signals
stim_proc : process
begin
if input_data < 127 then
wait until BUSY = '0' and RESET_N = '1';
ADR <= std_logic_vector(unsigned(ADR) + 1);
DAT_WR <= std_logic_vector(unsigned(DAT_WR) + 1);
elsif unsigned(DAT_WR) > 126 then
wait;
end if;
end process;