diff --git a/init_ch7301c.ucf b/init_ch7301c.ucf index 34d1e65..1a1eb2f 100644 --- a/init_ch7301c.ucf +++ b/init_ch7301c.ucf @@ -25,7 +25,5 @@ NET "led(6)" LOC = AD24; NET "led(7)" LOC = AE24; NET "led_n" LOC = AF13; -NET "led_e" LOC = AG23; NET "led_s" LOC = AG12; -NET "led_w" LOC = AF23; NET "led_c" LOC = E8; diff --git a/init_ch7301c.vhd b/init_ch7301c.vhd index 6775bb1..3e53b84 100644 --- a/init_ch7301c.vhd +++ b/init_ch7301c.vhd @@ -4,33 +4,33 @@ library unisim; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; use ieee.numeric_std.all; --- Xilinx primitives (???) -use unisim.VComponents.all; entity init_ch7301c is + generic ( + input_clk: integer := 27_000_000; + address: std_logic_vector(6 downto 0) := "1110110" -- 0x76 + ); port ( clk: in std_logic; reset: in std_logic; + finished: buffer std_logic; + error: buffer std_logic; + i2c_scl: inout std_logic; i2c_sda: inout std_logic; + + -- tmp dvi_reset: out std_logic; - - dip: in std_logic_vector(7 downto 0); - led: out std_logic_vector(7 downto 0); - + dip: in std_logic_vector(7 downto 0); led_n: out std_logic; - led_e: out std_logic; led_s: out std_logic; - led_w: out std_logic; led_c: out std_logic ); end init_ch7301c; architecture Behavioral of init_ch7301c is - constant i2c_ch7301c: std_logic_vector(6 downto 0) := "1110110"; -- 0x76 - signal i2c_reset: std_logic := '1'; signal i2c_execute: std_logic := '0'; signal i2c_busy: std_logic; @@ -40,13 +40,10 @@ architecture Behavioral of init_ch7301c is signal i2c_data_in: std_logic_vector(7 downto 0); signal i2c_data_out: std_logic_vector(7 downto 0); signal i2c_error: std_logic; - - type states is (start, init, finished, error); - signal state: states := start; begin i2c_master: entity work.i2c_master generic map ( - input_clk => 27_000_000, + input_clk => input_clk, bus_clk => 100_000 ) port map ( clk => clk, @@ -62,80 +59,71 @@ begin sda => i2c_sda ); - led_n <= '1' when state = start else '0'; - led_e <= '1' when state = init else '0'; - led_s <= '1' when state = finished else '0'; - led_w <= '1' when state = error else '0'; + led_n <= error; + led_s <= finished; led_c <= reset; main: process(clk, reset) - variable delay_init: integer range 0 to 10_000 := 0; - variable busy_count: integer range 0 to 2 := 0; + -- ch7301c needs some time (>2µs) to init its i2c port after reset + constant max_delay: integer := input_clk / 200_000; -- 5µs + variable delay: integer range 0 to max_delay := 0; + variable busy_count: integer range 0 to 3 := 0; begin if reset = '1' then + delay := 0; busy_count := 0; - delay_init := 0; - state <= start; - + finished <= '0'; + error <= '0'; -- reset components dvi_reset <= '0'; + i2c_execute <= '0'; i2c_reset <= '0'; elsif rising_edge(clk) then - case state is - when start => - delay_init := delay_init + 1; + if delay = 5 then + -- init components + dvi_reset <= '1'; + i2c_reset <= '1'; + delay := delay + 1; + elsif delay = max_delay then + i2c_busy_old <= i2c_busy; -- remember old value + if i2c_busy_old = '0' and i2c_busy = '1' then + -- count rising edges on i2c_busy: + -- command was accepted, ready for new one + busy_count := busy_count + 1; + end if; - if delay_init = 5_000 then - -- start components - dvi_reset <= '1'; - i2c_reset <= '1'; - elsif delay_init = 10_000 then - delay_init := 0; - -- start i2c init - state <= init; - busy_count := 0; - end if; + if i2c_error = '1' then + -- abort on error + i2c_execute <= '0'; + error <= '1'; + busy_count := 3; + end if; - when init => - i2c_busy_old <= i2c_busy; -- remember old value - if i2c_busy_old = '0' and i2c_busy = '1' then - -- count rising edges on i2c_busy: - -- command was accepted, ready for new one - busy_count := busy_count + 1; - end if; - - if i2c_error = '1' then - -- abort on error + case busy_count is + when 0 => + -- no command accepted yet, insert first one + i2c_execute <= '1'; + i2c_write <= '1'; + i2c_address <= address; + i2c_data_in <= dip; + when 1 => + -- submit read command + i2c_write <= '0'; + when 2 => + -- read submitted, wait for results, no more commands i2c_execute <= '0'; - state <= error; - end if; - - case busy_count is - when 0 => - -- no command accepted yet, insert first one - i2c_execute <= '1'; - i2c_write <= '1'; - i2c_address <= i2c_ch7301c; - i2c_data_in <= dip; - when 1 => - -- submit read command - i2c_write <= '0'; - when 2 => - -- read submitted, wait for results, no more commands - i2c_execute <= '0'; - if i2c_busy = '0' then - led <= i2c_data_out; - busy_count := 0; - state <= finished; - end if; - end case; - - when finished => - null; - - when error => - null; - end case; + if i2c_busy = '0' then + led <= i2c_data_out; + busy_count := 3; + end if; + when 3 => + -- finished! + finished <= '1'; + null; + end case; + else + delay := delay + 1; + end if; end if; end process main;