From a86cd90384aa1bff9309fcd97bbca42c59689772 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Klemens=20Sch=C3=B6lhorn?= Date: Wed, 22 Nov 2017 04:09:01 +0100 Subject: [PATCH] Fixup i2c init module --- dvi_test.xise | 6 +-- init_ch7301c.ucf | 20 +++++++- init_ch7301c.vhd | 124 +++++++++++++++++++++++++++++++++++------------ 3 files changed, 111 insertions(+), 39 deletions(-) diff --git a/dvi_test.xise b/dvi_test.xise index 704573e..50b0201 100644 --- a/dvi_test.xise +++ b/dvi_test.xise @@ -33,9 +33,6 @@ - - - @@ -377,8 +374,7 @@ - - + diff --git a/init_ch7301c.ucf b/init_ch7301c.ucf index 09ff0d3..34d1e65 100644 --- a/init_ch7301c.ucf +++ b/init_ch7301c.ucf @@ -1,6 +1,19 @@ +NET "clk" LOC = AG18; +NET "clk" PERIOD = 27 MHz HIGH 50%; +NET "reset" LOC = AJ6; # center switch NET "i2c_scl" LOC = U27; NET "i2c_sda" LOC = T29; +NET "dvi_reset" LOC = AK6; + +NET "dip(0)" LOC = AC24; +NET "dip(1)" LOC = AC25; +NET "dip(2)" LOC = AE26; +NET "dip(3)" LOC = AE27; +NET "dip(4)" LOC = AF26; +NET "dip(5)" LOC = AF25; +NET "dip(6)" LOC = AG27; +NET "dip(7)" LOC = U25; NET "led(0)" LOC = H18; NET "led(1)" LOC = L18; @@ -11,5 +24,8 @@ NET "led(5)" LOC = AD25; NET "led(6)" LOC = AD24; NET "led(7)" LOC = AE24; -NET "clk" LOC = AG18; -NET "clk" PERIOD = 27 MHz HIGH 50%; +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 0b903dc..6775bb1 100644 --- a/init_ch7301c.vhd +++ b/init_ch7301c.vhd @@ -10,15 +10,28 @@ use unisim.VComponents.all; entity init_ch7301c is port ( clk: in std_logic; + reset: in std_logic; i2c_scl: inout std_logic; i2c_sda: inout std_logic; + dvi_reset: out std_logic; - led: out std_logic_vector(7 downto 0) + dip: in std_logic_vector(7 downto 0); + + led: out 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; signal i2c_busy_old: std_logic; @@ -26,6 +39,10 @@ architecture Behavioral of init_ch7301c is signal i2c_write: std_logic; 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 ( @@ -33,47 +50,90 @@ begin bus_clk => 100_000 ) port map ( clk => clk, - reset_n => '1', + reset_n => i2c_reset, ena => i2c_execute, addr => i2c_address, rw => not i2c_write, data_wr => i2c_data_in, busy => i2c_busy, data_rd => i2c_data_out, - ack_error => open, - sda => i2c_scl, - scl => i2c_sda + ack_error => i2c_error, + scl => i2c_scl, + sda => i2c_sda ); - main: process(clk) - variable busy_count: integer range 0 to 3 := 0; - begin - if rising_edge(clk) 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 ascepted, read for new one - busy_count := busy_count + 1; - end if; + 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_c <= reset; - case busy_count is - when 0 => - -- no command eccepted yet, insert first one - i2c_execute <= '1'; - i2c_write <= '1'; - i2c_address <= "0111011"; -- 0x76 - i2c_data_in <= "01001001"; -- read power status of the chip (0x49) - 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 <= not i2c_data_out; + main: process(clk, reset) + variable delay_init: integer range 0 to 10_000 := 0; + variable busy_count: integer range 0 to 2 := 0; + begin + if reset = '1' then + busy_count := 0; + delay_init := 0; + state <= start; + + -- reset components + dvi_reset <= '0'; + i2c_reset <= '0'; + elsif rising_edge(clk) then + case state is + when start => + delay_init := delay_init + 1; + + 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; - when 3 => - -- finnished, stay here + + 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 + 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; end if;