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="Implementation" xil_pn:seqID="0"/>
</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">
<association xil_pn:name="BehavioralSimulation" xil_pn:seqID="106"/>
<association xil_pn:name="Implementation" xil_pn:seqID="0"/>
@ -377,8 +374,7 @@
</properties>
<bindings>
<binding xil_pn:location="/main" xil_pn:name="main.ucf"/>
<binding xil_pn:location="/main" xil_pn:name="init_ch7301c.ucf"/>
<binding xil_pn:location="/init_ch7301c" xil_pn:name="init_ch7301c.ucf"/>
</bindings>
<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_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;

View File

@ -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;