/* i2c master peripheral i2c frequency = clock frequency / 128 when fire = 0b1, a command starts. command = cmd_data(9..8) command 0b00 : i2c start command 0b01 : send a byte data data input = cmd_data(7..0) command 0b10: i2c end */ process i2c(clkin uint#1 clk, rstin uint#1 rst, out uint#1 latch sda, out uint#1 latch scl, in uint#1 fire, in uint#10 cmd_data, out uint#1 en comp) { uint#11 ctr; uint#8 d = 0; scl = 1; sda = 1; I2C_WAIT: { uint#10 cd = cmd_data; uint#2 cmd = cd(9..8); uint#8 data = cd(7..0); uint#1 f = fire; ctr = 0; if (~f) goto I2C_WAIT; else if (cmd == 0) goto I2C_START; else if (cmd == 1) { d = data; goto I2C_SEND; } else goto I2C_STOP; } I2C_START: scl = 1; sda = ~ctr(6); ctr++; if (ctr(6..0) != 0) goto I2C_START; else { comp = 1; goto I2C_WAIT; } I2C_SEND: scl = ctr(6)^ctr(5); sda = ctr(10)?1:d(7); ctr++; if (ctr(6..0) == 0) { if (ctr(10..7) == 9) { comp = 1; goto I2C_WAIT; } else { d = d(6..0)@0b0; goto I2C_SEND; } } else goto I2C_SEND; I2C_STOP: scl = 1; sda = ctr(6); ctr++; if (ctr(6..0) != 0) goto I2C_STOP; else { comp = 1; goto I2C_WAIT; } } combinational open_drain (in uint#1 I, out uint#1 tristate O) { if (~I) O = 0; } /* in top level instanciate like the following. toplevel logicboy( in uint#1 clk, in uint#1 rst, inout uint#1 pullup lcd_sda, inout uint#1 pullup lcd_scl, ... ) { com uint#1 i2c_sda, i2c_scl; com uint#12 en i2c_cmd_data; com uint#1 en i2c_comp; ... i2c(clk, rst, i2c_sda, i2c_scl, i2c_cmd_data en, i2c_cmd_data, i2c_comp); open_drain(i2c_sda, lcd_sda); open_drain(i2c_scl, lcd_scl); } */