📄 libreria_i2c.vhd
字号:
-- un '0' en el biestable de salida
-- para ir preparando la condicion de
-- START.
load_new <= '0';
inc_punt <= '0';
inc_sel_byte <= '0';
reset_sel_byte <= '0';
ENespera64 <= '0';
ENespera128 <= '0';
ready <= '1';
-- CONTROL SCL.
preset_div <= '1';
reset_div <= '0';
OESCL <= '0';
-- CONTROL SDA.
reset_bit <= '1';
load_bit <= '0';
OESDA <= '0';
if (trans = '1') then
siguiente <= captura_datos;
else
siguiente <= reposo;
end if;
when captura_datos =>
-- Se ha detectado una orden de inicio
-- de transferencia.
-- Cargamos tanto la direccion como el
-- dato en los registros de entrada.
-- Se supone que cuando se da esta orden
-- de inicio de transferencia, estos 2
-- bytes estan preparados en los buses
-- de entrada a ambos registros.
-- Reseteamos el puntero de bytes.
-- Habilitamos la salida de SCL.
load_new <= '1';
inc_punt <= '0';
inc_sel_byte <= '0';
reset_sel_byte <= '1';
ENespera64 <= '0';
ENespera128 <= '0';
ready <= '0';
-- CONTROL SCL.
preset_div <= '0';
reset_div <= '0';
OESCL <= '1';
-- CONTROL SDA.
reset_bit <= '0';
load_bit <= '0';
OESDA <= '0';
siguiente <= cond_start;
when cond_start =>
-- Generamos la condicion de start
-- poniendo SDA a '0' con SCL a '1'.
-- Lo que hacemos es dejar salir el
-- contenido del biestable de salida,
-- el cual precargamos al principio con
-- un '0'.
load_new <= '0';
inc_punt <= '0';
inc_sel_byte <= '0';
reset_sel_byte <= '0';
ENespera64 <= '0';
ENespera128 <= '0';
ready <= '0';
-- CONTROL SCL.
preset_div <= '0';
reset_div <= '0';
OESCL <= '1';
-- CONTROL SDA.
reset_bit <= '0';
load_bit <= '0';
OESDA <= '1';
siguiente <= esp_SCL0;
when esp_SCL0 =>
-- Esperamos a que SCL sea '0'
-- para poder poner el bit a transmitir
-- sobre la linea SDA.
load_new <= '0';
inc_punt <= '0';
inc_sel_byte <= '0';
reset_sel_byte <= '0';
ENespera64 <= '0';
ENespera128 <= '0';
ready <= '0';
-- CONTROL SCL.
preset_div <= '0';
reset_div <= '0';
OESCL <= '1';
-- CONTROL SDA.
reset_bit <= '0';
load_bit <= '0';
OESDA <= '1';
if (SCL = '0') then
siguiente <= espera_64;
else
siguiente <= esp_SCL0;
end if;
when espera_64 =>
-- SCL = '0'.
-- Esperamos a que pasen 64 Tclk
-- para capturar el bit a transmitir
-- en el latch de salida. Asi
-- aseguramos que SDA solo conmuta
-- en la mitad del semiperiodo '0'
-- de SCL.
load_new <= '0';
inc_punt <= '0';
inc_sel_byte <= '0';
reset_sel_byte <= '0';
ENespera64 <= '1';
ENespera128 <= '0';
ready <= '0';
-- CONTROL SCL.
preset_div <= '0';
reset_div <= '0';
OESCL <= '1';
-- CONTROL SDA.
reset_bit <= '0';
load_bit <= '0';
OESDA <= '1';
if (fin_espera64= '1') then
siguiente <= envia_bit;
else
siguiente <= espera_64;
end if;
when envia_bit =>
-- Capturamos el bit a transmitir
-- en el biestable de salida, es decir,
-- ponemos el bit en SDA.
load_new <= '0';
inc_punt <= '0';
inc_sel_byte <= '0';
reset_sel_byte <= '0';
ENespera64 <= '0';
ENespera128 <= '0';
ready <= '0';
-- CONTROL SCL.
preset_div <= '0';
reset_div <= '0';
OESCL <= '1';
-- CONTROL SDA.
reset_bit <= '0';
load_bit <= '1';
OESDA <= '1';
siguiente <= esp_SCL1;
when esp_SCL1 =>
-- Esperamos a que SCL sea '1'.
load_new <= '0';
inc_punt <= '0';
inc_sel_byte <= '0';
reset_sel_byte <= '0';
ENespera64 <= '0';
ENespera128 <= '0';
ready <= '0';
-- CONTROL SCL.
preset_div <= '0';
reset_div <= '0';
OESCL <= '1';
-- CONTROL SDA.
reset_bit <= '0';
load_bit <= '0';
OESDA <= '1';
if (SCL = '1') then
siguiente <= hold_bit;
else
siguiente <= esp_SCL1;
end if;
when hold_bit =>
-- Mantenemos el bit cargado en el
-- biestable de salida durante todo el
-- tiempo en que SCL = '1' para respetar
-- el protocolo.
load_new <= '0';
inc_punt <= '0';
inc_sel_byte <= '0';
reset_sel_byte <= '0';
ENespera64 <= '0';
ENespera128 <= '0';
ready <= '0';
-- CONTROL SCL.
preset_div <= '0';
reset_div <= '0';
OESCL <= '1';
-- CONTROL SDA.
reset_bit <= '0';
load_bit <= '0';
OESDA <= '1';
if (SCL = '0') then
siguiente <= nuevo_bit;
else
siguiente <= hold_bit;
end if;
when nuevo_bit =>
-- Llegamos a SCL = '0' de nuevo.
-- Hemos de evaluar si quedan mas bits
-- por transmitir del byte en cuestion.
-- Esperamos 64 Tclk antes de cambiar
-- SDA.
load_new <= '0';
inc_punt <= '0';
inc_sel_byte <= '0';
reset_sel_byte <= '0';
ENespera64 <= '1';
ENespera128 <= '0';
ready <= '0';
-- CONTROL SCL.
preset_div <= '0';
reset_div <= '0';
OESCL <= '1';
-- CONTROL SDA.
reset_bit <= '0';
load_bit <= '0';
OESDA <= '1';
if (fin_espera64 = '1') then
siguiente <= mira_puntero;
else
siguiente <= nuevo_bit;
end if;
when mira_puntero =>
-- Hemos de cambiar SDA segun el valor
-- del puntero. Si puntero = "111"
-- significa que hemos enviado el ultimo
-- bit y debemos poner SDA en alta
-- impedancia para recibir el ACK.
-- Si puntero < "111" aun quedan bits
-- por enviar.
load_new <= '0';
inc_punt <= '0';
inc_sel_byte <= '0';
reset_sel_byte <= '0';
ENespera64 <= '0';
ENespera128 <= '0';
ready <= '0';
-- CONTROL SCL.
preset_div <= '0';
reset_div <= '0';
OESCL <= '1';
-- CONTROL SDA.
reset_bit <= '0';
load_bit <= '0';
OESDA <= '1';
if (puntero = "111") then
siguiente <= reset_puntero;
else
siguiente <= incrementa_puntero;
end if;
when incrementa_puntero =>
-- Incrementamos el puntero para
-- seleccionar el siguiente bit a enviar.
load_new <= '0';
inc_punt <= '1';
inc_sel_byte <= '0';
reset_sel_byte <= '0';
ENespera64 <= '0';
ENespera128 <= '0';
ready <= '0';
-- CONTROL SCL.
preset_div <= '0';
reset_div <= '0';
OESCL <= '1';
-- CONTROL SDA.
reset_bit <= '0';
load_bit <= '0';
OESDA <= '1';
siguiente <= espera_cargar_bit;
when espera_cargar_bit =>
-- Introducimos este periodo de espera
-- de 1 Tclk para dar tiempo a la
-- actualizacion del puntero.
-- Despues volvemos al estado en que
-- generamos la salida del bit a SDA.
load_new <= '0';
inc_punt <= '0';
inc_sel_byte <= '0';
reset_sel_byte <= '0';
ENespera64 <= '0';
ENespera128 <= '0';
ready <= '0';
-- CONTROL SCL.
preset_div <= '0';
reset_div <= '0';
OESCL <= '1';
-- CONTROL SDA.
reset_bit <= '0';
load_bit <= '0';
OESDA <= '1';
siguiente <= envia_bit;
when reset_puntero =>
-- El puntero senalaba al ultimo bit.
-- Lo incrementamos para ponerlo a 0 y
-- asi volver a senalar al primero.
-- Despues ponemos SDA en alta impedancia
-- para recibir el ACK.
load_new <= '0';
inc_punt <= '1';
inc_sel_byte <= '0';
reset_sel_byte <= '0';
ENespera64 <= '0';
ENespera128 <= '0';
ready <= '0';
-- CONTROL SCL.
preset_div <= '0';
reset_div <= '0';
OESCL <= '1';
-- CONTROL SDA.
reset_bit <= '0';
load_bit <= '0';
OESDA <= '1';
siguiente <= comprueba_ACK1;
when comprueba_ACK1 =>
-- Hemos transmitido el byte completo.
-- Hacemos que SDA este en alta
-- impedancia para que el procesador
-- de video pueda transmitir el ACK.
-- Esperamos a que SCL sea '1' para
-- comprobar el valor de SDA.
load_new <= '0';
inc_punt <= '0';
inc_sel_byte <= '0';
reset_sel_byte <= '0';
ENespera64 <= '0';
ENespera128 <= '0';
ready <= '0';
-- CONTROL SCL.
preset_div <= '0';
reset_div <= '0';
OESCL <= '1';
-- CONTROL SDA.
reset_bit <= '0';
load_bit <= '0';
OESDA <= '0';
if (SCL = '1') then
siguiente <= comprueba_ACK2;
else
siguiente <= comprueba_ACK1;
end if;
when comprueba_ACK2 =>
-- SCL = '1', esperamos 64 Tclk para
-- mirar el valor de SDA a mitad del
-- semiperiodo '1' de SCL.
load_new <= '0';
inc_punt <= '0';
inc_sel_byte <= '0';
reset_sel_byte <= '0';
ENespera64 <= '1';
ENespera128 <= '0';
ready <= '0';
-- CONTROL SCL.
preset_div <= '0';
reset_div <= '0';
OESCL <= '1';
-- CONTROL SDA.
reset_bit <= '0';
load_bit <= '0';
OESDA <= '0';
if (fin_espera64 = '1') then
siguiente <= comprueba_ACK3;
else
siguiente <= comprueba_ACK2;
end if;
when comprueba_ACK3 =>
-- En este momento comprobamos si SDA
-- esta a '0' (ACK).
-- Tambien determinamos si hemos enviado
-- los tres bytes necesarios para
-- especificar la escritura de un
-- registro interno del procesador de
-- video via I2C, o bien, aun nos queda
-- alguno por enviar.
load_new <= '0';
inc_punt <= '0';
inc_sel_byte <= '0';
reset_sel_byte <= '0';
ENespera64 <= '0';
ENespera128 <= '0';
ready <= '0';
-- CONTROL SCL.
preset_div <= '0';
reset_div <= '0';
OESCL <= '1';
-- CONTROL SDA.
reset_bit <= '0';
load_bit <= '0';
OESDA <= '0';
if (SDAent = '0') then
-- Si detectamos ACK correcto...
if (punt_byte = "10") then
siguiente <= set_punt_byte;
else
siguiente <= sig_byte;
end if;
else
-- Si no hay ACK por parte del
-- procesador de video...
siguiente <= STOP1;
end if;
when sig_byte =>
-- Se ha detectado con exito el ACK del
-- ultimo byte enviado pero nos quedan
-- bytes por enviar para completar la
-- escritura.
-- Aqui hacemos que el multiplexor
-- encargado de seleccionar el byte a
-- transmitir, seleccione al siguiente.
load_new <= '0';
inc_punt <= '0';
inc_sel_byte <= '1';
reset_sel_byte <= '0';
ENespera64 <= '0';
ENespera128 <= '0';
ready <= '0';
-- CONTROL SCL.
preset_div <= '0';
reset_div <= '0';
OESCL <= '1';
-- CONTROL SDA.
reset_bit <= '0';
load_bit <= '0';
OESDA <= '0';
siguiente <= esp_SCL0_sigbyte;
when esp_SCL0_sigbyte =>
-- Esperamos a que SCL sea '0' para
-- preparar la transmision del
-- siguiente byte.
load_new <= '0';
inc_punt <= '0';
inc_sel_byte <= '0';
reset_sel_byte <= '0';
ENespera64 <= '0';
ENespera128 <= '0';
ready <= '0';
-- CONTROL SCL.
preset_div <= '0';
reset_div <= '0';
OESCL <= '1';
-- CONTROL SDA.
reset_bit <= '0';
load_bit <= '0';
OESDA <= '0';
if (SCL = '0') then
siguiente <= esp_sig_dato;
else
siguiente <= esp_SCL0_sigbyte;
end if;
when esp_sig_dato =>
-- Reseteamos el divisor mientras
-- incluimos una espera adicional de
-- 128 Tclk antes de enviar el siguiente
-- byte (dato).
load_new <= '0';
inc_punt <= '0';
inc_sel_byte <= '0';
reset_sel_byte <= '0';
ENespera64 <= '0';
ENespera128 <= '1';
ready <= '0';
-- CONTROL SCL.
preset_div <= '0';
reset_div <= '1';
OESCL <= '1';
-- CONTROL SDA.
reset_bit <= '0';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -