Codec WM8731 Audio Codec
Codec Coder / Decoder Audio, Video Compression/decompression signal coding 2 tj
WM8731 3 tj
WM8731 Data Path Basic Connection 4 tj
WM8731 Data Path Basic Timing 5 tj
WM8731 Data Path 16 to 32 bit data Left justified mode 6 tj
WM8731 - Control I2C control interface 7 tj
WM8731 - Control 16 bit word (7 addr, 9 data) 8 tj
Two Wire Interface Overview 8 bit synchronous shift register used to communicate externally 9 bit total communication packet uni-directional Most often used to communicate with peripherals displays, sensors, converters Supports multiple masters and multiple slaves 4 modes of operation Master Receive Master Transmit Slave Receive Slave Transmit 9 tj
Two Wire Interface Overview Open drain configuration outputs only pull down pull up resistors or current sources pull up 10 tj
Two Wire Interface TWI Timing SDA data line SCL clock line Data must be valid during the entire positive clock cycle time Note: data changes occur during SCL low 11 tj
Two Wire Interface TWI Timing Special timing requirements for start transmission stop transmission repeated start transition master does not relinquish the bus in this mode 12 tj
Two Wire Interface TWI Timing Addressing Indicate which slave to transmit to or receive from by first transmitting the address of the desired device Often this value is hardwired via external pins on the slave device 7 bits for each address 13 tj
Two Wire Interface TWI Timing R/W bit indicates a read or write operation is to follow Read is active high ACK The master drives the data bus from start through the R/W bit and then releases the bus The slave then pulls down the bus in the last clock cycle to indicate a completed transmission 14 tj
Two Wire Interface TWI Timing ACK cont d If the master fails to see the slave pull down the bus in the 9 th clock cycle (NACK) Transmission failed Some sort of error action is required 15 tj
Two Wire Interface TWI Timing Data packet After getting an ACK on the address data can be sent 8 bits of data 1 bit for a data ACK This can be repeated many times 16 tj
Control programming I2C interface 1st transmission Device address, R/W 2 nd transmission Register address + Data bit 8 3 rd transmission Data bits 7-0 17 tj
Control programming src: Chu 18 tj
Control programming src: Chu 19 tj
Control programming tristate bidirectional ¼ bit resolution clk 24 bit data register 1 bit 100Kbit/s Buffer SDA SCL 50MHz Counter Control # bits # bytes 20 tj
Control programming CLK Reset Din(23:0) wr_i2c I2C Block sclk sdat Idle fail done 21 tj
Control programming Chu uses the pullup for SDAT = 1 i2c_sdat <= Z when sdat_reg = 1 else 0 ; 22 tj
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity i2c is port ( clk, reset: in std_logic; din: in std_logic_vector(23 downto 0); wr_i2c: in std_logic; i2c_sclk: out std_logic; i2c_sdat: inout std_logic; i2c_idle, i2c_fail: out std_logic; i2c_done_tick: out std_logic ); end i2c; architecture arch of i2c is constant HALF: integer := 249; -- 10us/20ns/2 = 250 constant QUTR: integer := 125; -- 10us/20ns/4 = 125 constant C_WIDTH: integer := 8; type statetype is ( idle, start, scl_begin, data1, data2, data3, ack1, ack2, ack3, scl_end, stop, turn); signal state_reg, state_next: statetype; signal c_reg,c_next: unsigned(c_width-1 downto 0); signal data_reg, data_next: std_logic_vector(23 downto 0); signal bit_reg, bit_next: unsigned(2 downto 0); signal byte_reg, byte_next: unsigned(1 downto 0); signal sdat_out, sclk_out: std_logic; signal sdat_reg, sclk_reg: std_logic; signal ack_reg, ack_next: std_logic; begin -- ========================================================= ======== -- output -- ========================================================= ======== -- buffer for sda and scl lines process (clk, reset) begin if reset='1' then sdat_reg <= '1'; sclk_reg <= '1'; elsif (clk'event and clk='1') then sdat_reg <= sdat_out; sclk_reg <= sclk_out; end process; -- only master drives scl line i2c_sclk <= sclk_reg; -- i2c_sdat are with pull-up resistors -- and becomes high when not driven i2c_sdat <= 'Z' when sdat_reg='1' else '0'; -- codac fails to acknowledge properly i2c_fail <= '1' when ack_reg='1' else '0'; 23 tj
-- -- next-state logic ========================================================= process(state_reg,bit_reg,byte_reg,data_reg,c_reg,ack_reg, ======== din,wr_i2c,i2c_sdat) -- fsmd for transmitting three bytes begin -- state_next <= state_reg; ========================================================= sclk_out <= '1'; ======== sdat_out <= '1'; -- registers c_next <= c_reg + 1; -- timer counts continuouisely process (clk, reset) bit_next <= bit_reg; begin byte_next <= byte_reg; if reset='1' then data_next <= data_reg; state_reg <= idle; ack_next <= ack_reg; c_reg <= (others=>'0'); i2c_done_tick <='0'; bit_reg <= (others=>'0'); i2c_idle <='0'; byte_reg <= (others=>'0'); case state_reg is data_reg <= (others=>'0'); when idle => ack_reg <= '1'; i2c_idle <= '1'; elsif (clk'event and clk='1') then if wr_i2c='1' then state_reg <= state_next; data_next <= din; c_reg <= c_next; bit_next <= "000"; bit_reg <= bit_next; byte_next <="00"; byte_reg <= byte_next; c_next <= (others=>'0'); data_reg <= data_next; state_next <= start; ack_reg <= ack_next; when start => -- start condition end process; sdat_out <= '0'; if c_reg=half then c_next <= (others=>'0'); state_next <= scl_begin; 24 tj
when scl_begin => -- 1st half of scl=0 sclk_out <= '0'; if c_reg=qutr then c_next <= (others=>'0'); state_next <= data1; when data1 => sdat_out <= data_reg(23); sclk_out <= '0'; if c_reg=qutr then c_next <= (others=>'0'); state_next <= data2; when data2 => sdat_out <= data_reg(23); if c_reg=half then c_next <= (others=>'0'); state_next <= data3; when data3 => sdat_out <= data_reg(23); sclk_out <= '0'; if c_reg=qutr then c_next <= (others=>'0'); if bit_reg=7 then -- done with 8 bits state_next <= ack1; else data_next <= data_reg(22 downto 0) & '0'; bit_next <= bit_reg + 1; state_next <= data1; when ack1 => sclk_out <= '0'; if c_reg=qutr then c_next <= (others=>'0'); state_next <= ack2; when ack2 => if c_reg=half then c_next <= (others=>'0'); state_next <= ack3; ack_next <= i2c_sdat; -- read ack from slave when ack3 => sclk_out <= '0'; if c_reg=qutr then c_next <= (others=>'0'); if ack_reg = '1' then -- slave fails to ack state_next <= scl_end; else if byte_reg=2 then -- done with 3 bytes state_next <= scl_end; else bit_next <= "000"; byte_next <= byte_reg + 1; data_next <= data_reg(22 downto 0) & '0'; state_next <= data1; 25 tj
when scl_end => -- 2nd half of scl=0 sclk_out <= '0'; sdat_out <= '0'; if c_reg=qutr then c_next <= (others=>'0'); state_next <= stop; when stop => -- stop condition sdat_out <= '0'; if c_reg=half then c_next <= (others=>'0'); state_next <= turn; when turn => -- turnaround time if c_reg=half then state_next <= idle; i2c_done_tick <= '1'; end case; end process; end arch; 26 tj