Fixup i2c init module

This commit is contained in:
Klemens Schölhorn 2017-11-22 04:09:01 +01:00
parent 168102e13b
commit a86cd90384
3 changed files with 111 additions and 39 deletions

View File

@ -33,9 +33,6 @@
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="65"/> <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="65"/>
<association xil_pn:name="Implementation" xil_pn:seqID="0"/> <association xil_pn:name="Implementation" xil_pn:seqID="0"/>
</file> </file>
<file xil_pn:name="main.ucf" xil_pn:type="FILE_UCF">
<association xil_pn:name="Implementation" xil_pn:seqID="0"/>
</file>
<file xil_pn:name="ipcore_dir/clock_source.xaw" xil_pn:type="FILE_XAW"> <file xil_pn:name="ipcore_dir/clock_source.xaw" xil_pn:type="FILE_XAW">
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="106"/> <association xil_pn:name="BehavioralSimulation" xil_pn:seqID="106"/>
<association xil_pn:name="Implementation" xil_pn:seqID="0"/> <association xil_pn:name="Implementation" xil_pn:seqID="0"/>
@ -377,8 +374,7 @@
</properties> </properties>
<bindings> <bindings>
<binding xil_pn:location="/main" xil_pn:name="main.ucf"/> <binding xil_pn:location="/init_ch7301c" xil_pn:name="init_ch7301c.ucf"/>
<binding xil_pn:location="/main" xil_pn:name="init_ch7301c.ucf"/>
</bindings> </bindings>
<libraries/> <libraries/>

View File

@ -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_scl" LOC = U27;
NET "i2c_sda" LOC = T29; 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(0)" LOC = H18;
NET "led(1)" LOC = L18; NET "led(1)" LOC = L18;
@ -11,5 +24,8 @@ NET "led(5)" LOC = AD25;
NET "led(6)" LOC = AD24; NET "led(6)" LOC = AD24;
NET "led(7)" LOC = AE24; NET "led(7)" LOC = AE24;
NET "clk" LOC = AG18; NET "led_n" LOC = AF13;
NET "clk" PERIOD = 27 MHz HIGH 50%; NET "led_e" LOC = AG23;
NET "led_s" LOC = AG12;
NET "led_w" LOC = AF23;
NET "led_c" LOC = E8;

View File

@ -10,15 +10,28 @@ use unisim.VComponents.all;
entity init_ch7301c is entity init_ch7301c is
port ( port (
clk: in std_logic; clk: in std_logic;
reset: in std_logic;
i2c_scl: inout std_logic; i2c_scl: inout std_logic;
i2c_sda: 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; end init_ch7301c;
architecture Behavioral of init_ch7301c is 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_execute: std_logic := '0';
signal i2c_busy: std_logic; signal i2c_busy: std_logic;
signal i2c_busy_old: 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_write: std_logic;
signal i2c_data_in: std_logic_vector(7 downto 0); signal i2c_data_in: std_logic_vector(7 downto 0);
signal i2c_data_out: 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 begin
i2c_master: entity work.i2c_master generic map ( i2c_master: entity work.i2c_master generic map (
@ -33,47 +50,90 @@ begin
bus_clk => 100_000 bus_clk => 100_000
) port map ( ) port map (
clk => clk, clk => clk,
reset_n => '1', reset_n => i2c_reset,
ena => i2c_execute, ena => i2c_execute,
addr => i2c_address, addr => i2c_address,
rw => not i2c_write, rw => not i2c_write,
data_wr => i2c_data_in, data_wr => i2c_data_in,
busy => i2c_busy, busy => i2c_busy,
data_rd => i2c_data_out, data_rd => i2c_data_out,
ack_error => open, ack_error => i2c_error,
sda => i2c_scl, scl => i2c_scl,
scl => i2c_sda sda => i2c_sda
); );
main: process(clk) led_n <= '1' when state = start else '0';
variable busy_count: integer range 0 to 3 := 0; led_e <= '1' when state = init else '0';
begin led_s <= '1' when state = finished else '0';
if rising_edge(clk) then led_w <= '1' when state = error else '0';
i2c_busy_old <= i2c_busy; -- remember old value led_c <= reset;
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;
case busy_count is main: process(clk, reset)
when 0 => variable delay_init: integer range 0 to 10_000 := 0;
-- no command eccepted yet, insert first one variable busy_count: integer range 0 to 2 := 0;
i2c_execute <= '1'; begin
i2c_write <= '1'; if reset = '1' then
i2c_address <= "0111011"; -- 0x76 busy_count := 0;
i2c_data_in <= "01001001"; -- read power status of the chip (0x49) delay_init := 0;
when 1 => state <= start;
-- submit read command
i2c_write <= '0'; -- reset components
when 2 => dvi_reset <= '0';
-- read submitted, wait for results, no more commands i2c_reset <= '0';
i2c_execute <= '0'; elsif rising_edge(clk) then
if i2c_busy = '0' then case state is
led <= not i2c_data_out; 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; 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; null;
end case; end case;
end if; end if;