The i2s
IP is a fully parameterised soft IP implementing the Philips compatible I2S interface. The IP features an APB4 slave interface, fully compliant with the AMBA APB Protocol Specification v2.0. Now only support keyboard.
- Compatible with Phillps I2S standard
- Half duplex serial data transmission(send or receive only)
- Audio CODEC master or slave mode support
- Programmable serial clock polarity
- Programmable prescaler
- max division factor is up to 2^16
- 8KHz, 12KHz, 16KHz, 24KHz, 32KHz, 48KHz or 96KHz sample rate
- Stereo or left channel and right channel only mode
- MSB-justified, LSB-justified or I2S Phillps mode
- 8, 16, 24 or 32 bits data transmission size
- Independent send and receive FIFO
- 16~64 data depth
- empty or no-emtpy status flag
- Maskable send or receive interrupt and programmable threshold
- Static synchronous design
- Full synthesizable
port name | type | description |
---|---|---|
apb4 | interface | apb4 slave interface |
i2c -> | interface | i2c slave interface |
i2c.scl_i |
input | i2c clock input |
i2c.scl_o |
output | i2c clock output |
i2c.scl_dir_o |
output | i2c clock tri-state ctrl |
i2c.sda_i |
input | i2c data input |
i2c.sda_o |
output | i2c data output |
i2c.sda_dir_o |
output | i2c data tri-state ctrl |
i2c.irq_o |
output | i2c irq output |
name | offset | length | description |
---|---|---|---|
CTRL | 0x0 | 4 | control register |
DIV | 0x4 | 4 | divide register |
TXR | 0x8 | 4 | transmit register |
RXR | 0xC | 4 | receive register |
STAT | 0x10 | 4 | state register |
bit | access | description |
---|---|---|
[31:26] |
none | reserved |
[25:21] |
RW | RXTH |
[20:16] |
RW | TXTH |
[15:14] |
RW | DTL |
[13:12] |
RW | CHL |
[11:10] |
RW | CHM |
[9:8] |
RW | FMT |
[7:7] |
RW | WM |
[6:6] |
RW | LSB |
[5:5] |
RW | POL |
[4:4] |
RW | LSR |
[3:3] |
RW | CLR |
[2:2] |
RW | RXIE |
[1:1] |
RW | TXIE |
[0:0] |
RW | EN |
reset value: 0x0000_0000
-
RXTH: receive fifo irq trigger threshold
-
TXTH: transmit fifo irq trigger threshold
-
DTL: data size in one transmit
DTL = 2'b00
: 8 bitsDTL = 2'b01
: 16 bitsDTL = 2'b10
: 24 bitsDTL = 2'b11
: 32 bits
-
CHL:
CHL = 2'b00
: 8 bitsCHL = 2'b01
: 16 bitsCHL = 2'b10
: 24 bitsCHL = 2'b11
: 32 bits
-
CHM: mode
CHM = 2'b00
: stero modeCHM = 2'b01
: left channelCHM = 2'b10
: right channelCHM = 2'b11
: none
bit | access | description |
---|---|---|
[31:16] |
none | reserved |
[15:0] |
RW | PSCR |
reset value: 0x0000_FFFF
- PSCR: 16-bit prescaler value
bit | access | description |
---|---|---|
[31:8] |
none | reserved |
[7:0] |
RW | DATA |
reset value: 0x0000_0000
- DATA: transmit data
[7:1]
: upper 7 bits of DATA[0:0]
: LSB of DATA- address phase:
0
-> write to slave1
-> read from slave - data phase: LSB of DATA
- address phase:
bit | access | description |
---|---|---|
[31:8] |
none | reserved |
[7:0] |
RO | DATA |
reset value: 0x0000_0000
- DATA: receive data
bit | access | description |
---|---|---|
[31:8] |
none | reserved |
[7:7] |
WO | STA |
[6:6] |
WO | STO |
[5:5] |
WO | RD |
[4:4] |
WO | WR |
[3:3] |
WO | ACK |
[2:1] |
none | reserved |
[0:0] |
WO | IACK |
reset value: 0x0000_0000
-
STA: start command
STA = 1'b0
: dont send start commandSTA = 1'b1
: otherwise
-
STO: stop command
STO = 1'b0
: dont send stop commandSTO = 1'b1
: otherwise
-
RD: read from slave command
RD = 1'b0
: dont send read commandRD = 1'b1
: otherwise
-
WR: write to slave command
WR = 1'b0
: dont send write commandWR = 1'b1
: otherwise
-
ACK: read acknowledge
ACK = 1'b0
: send nack commandACK = 1'b1
: send ack command
-
IACK: interrupt acknowledge
IACK = 1'b0
: dont clear interrupt ack flagIACK = 1'b1
: otherwise
bit | access | description |
---|---|---|
[31:8] |
none | reserved |
[7:7] |
RO | RXK |
[6:6] |
RO | BSY |
[5:5] |
RO | AL |
[4:2] |
none | reserved |
[1:1] |
RO | TIP |
[0:0] |
RO | IF |
reset value: 0x0000_0000
-
RXK: receive acknowledge from slave
RXK = 1'b0
: receive ackRXK = 1'b1
: otherwise
-
BSY: i2c bus busy
BSY = 1'b0
: detect stop commandBSY = 1'b1
: detect start command
-
AL: arbitration lost
AL = 1'b0
: dont lost arbitAL = 1'b1
: otherwise
-
TIP: transmit in progress
TIP = 1'b0
: transmit doneTIP = 1'b1
: otherwise
-
IF: interrupt flag
IF = 1'b0
: interrupt is triggeredIF = 1'b1
: otherwise
These registers can be accessed by 4-byte aligned read and write. C-like pseudocode init operation:
i2c.PSCR = PSCR_16_bit // set the prescaler value
i2c.CTRL.EN = 1 // enable i2c core
write operation:
i2c.TXR = (SLAVE_ADDR_7_bit << 1) | 0 // send slave device addr
i2c.CMD.[STA, WR] = 1 // set start and write mode
while (i2c.SR.TIP == 0); // need TIP go to 1
while (i2c.SR.TIP != 0); // need TIP go to 0
if i2c.SR.RXK == 1: print('no receive ack')
i2c.TXR = SLAVE_SUB_ADDR_8_bit // send slave sub addr
i2c.CMD.WR = 1 // set start and write mode
while (i2c.SR.TIP == 0); // need TIP go to 1
while (i2c.SR.TIP != 0); // need TIP go to 0
if i2c.SR.RXK == 1: print('no receive ack')
...
i2c.TXR = DATA_8_bit // send data
i2c.CMD.WR = 1 // set start and write mode
while (i2c.SR.TIP == 0); // need TIP go to 1
while (i2c.SR.TIP != 0); // need TIP go to 0
if i2c.SR.RXK == 1: print('no receive ack')
...
i2c.CMD.STOP = 1 // send stop command
while (i2c.SR.BSY == 1) // wait bus idle
read operation:
i2c.TXR = (SLAVE_ADDR_7_bit << 1) | 0 // send slave device addr
i2c.CMD.[STA, WR] = 1 // set start and write mode
while (i2c.SR.TIP == 0); // need TIP go to 1
while (i2c.SR.TIP != 0); // need TIP go to 0
if i2c.SR.RXK == 1: print('no receive ack')
i2c.TXR = SLAVE_SUB_ADDR_8_bit // send slave sub addr
i2c.CMD.WR = 1 // set start and write mode
while (i2c.SR.TIP == 0); // need TIP go to 1
while (i2c.SR.TIP != 0); // need TIP go to 0
if i2c.SR.RXK == 1: print('no receive ack')
i2c.CMD.STOP = 1 // send stop command
while (i2c.SR.BSY == 1) // wait bus idle
i2c.TXR = (SLAVE_ADDR_7_bit << 1) | 1 // send slave device addr
i2c.CMD.[STA, WR] = 1 // set start and write mode
while (i2c.SR.TIP == 0); // need TIP go to 1
while (i2c.SR.TIP != 0); // need TIP go to 0
if i2c.SR.RXK == 1: print('no receive ack')
...
i2c.CMD.RD = 1 // set read mode
while (i2c.SR.TIP == 0); // need TIP go to 1
while (i2c.SR.TIP != 0); // need TIP go to 0
if i2c.SR.RXK == 1: print('no receive ack')
uint32_t recv_data = i2c.RXR // read the data
...
i2c.CMD.[STOP, RD] = 1 // set stop and read mode
while (i2c.SR.TIP == 0); // need TIP go to 1
while (i2c.SR.TIP != 0); // need TIP go to 0
if i2c.SR.RXK == 1: print('no receive ack')
uint32_t recv_data = i2c.RXR // read the last data