📄 libreria_i2c.vhd
字号:
library IEEE;
use IEEE.std_logic_1164.all;
package libreria_i2c is
-- Divisor, generador de SCL.
-- Divide los 50 MHz del reloj del sistema por 256 utilizando
-- un contador de 8 bits y tomando como salida al MSB.
component divisor port (
reset: in STD_LOGIC;
reloj: in STD_LOGIC;
clear: in STD_LOGIC;
set: in STD_LOGIC;
SCL: buffer STD_LOGIC
);
end component;
-- Buffer triestado de salida para SCL.
-- Controla el estado de alta impedancia (pull-up) de la linea
-- de reloj serie (SCL).
component bufferZ port (
ent : in STD_LOGIC;
OE : in STD_LOGIC;
sal : out STD_LOGIC
);
end component;
-- Definimos un registro que servira tanto para mantener la
-- subdireccion del registro interno del procesador de video
-- donde deseamos escribir el dato como al propio dato (lo
-- instanciaremos dos veces en el TOP).
component registro port (
reset: in STD_LOGIC;
reloj: in STD_LOGIC;
LE: in STD_LOGIC;
dat_in: in STD_LOGIC_VECTOR (7 downto 0);
dat_out: out STD_LOGIC_VECTOR (7 downto 0)
);
end component;
-- Definimos un multiplexor 3(x8):1(x8) que nos servira para
-- seleccionar a cada uno de los tres bytes que son necesarios
-- para la escritura de un registro interno del procesador de
-- video via I2C.
component mux_byte port (
byte2: in STD_LOGIC_VECTOR (7 downto 0);
byte1: in STD_LOGIC_VECTOR (7 downto 0);
byte0: in STD_LOGIC_VECTOR (7 downto 0);
sel: in STD_LOGIC_VECTOR (1 downto 0);
byte_sal: out STD_LOGIC_VECTOR (7 downto 0)
);
end component;
-- Definimos un contador de 2 bits que hara de puntero para
-- seleccionar mediante el multiplexor anterior, el byte
-- que vamos a transmitir.
component contador_byte port (
reset: in STD_LOGIC;
reloj: in STD_LOGIC;
clear: in STD_LOGIC;
inc: in STD_LOGIC;
cont: out STD_LOGIC_VECTOR (1 downto 0)
);
end component;
-- Definimos un multiplexor 8:1 que usaremos como serializador.
-- Tomara uno a uno los bits de la salida del multiplexor
-- 3(x8):1(x8) comenzando por el bit mas significativo para
-- respetar el protocolo de transferencia I2C.
component mux port (
ent: in STD_LOGIC_VECTOR (7 downto 0);
sel: in STD_LOGIC_VECTOR (2 downto 0);
sal: out STD_LOGIC
);
end component;
-- Definimos un contador que hara de puntero para determinar
-- el bit que sera seleccionado por cada multiplexor. De nuevo,
-- este componente lo instanciaremos dos veces en el TOP (una
-- por cada multiplexor).
component contador port (
reset: in STD_LOGIC;
reloj: in STD_LOGIC;
inc: in STD_LOGIC;
cont: out STD_LOGIC_VECTOR (2 downto 0)
);
end component;
-- Maquina de estados que controla el protocolo I2C.
-- Solo hay que suministrarle los 3 bytes a enviar. La maquina
-- los envia respetando las reglas del protocolo I2C.
component FSM_I2C port (
reloj: in STD_LOGIC;
reset: in STD_LOGIC;
trans: in STD_LOGIC;
fin_espera64: in STD_LOGIC;
fin_espera128: in STD_LOGIC;
puntero: in STD_LOGIC_VECTOR (2 downto 0);
SDAent: in STD_LOGIC;
SCL: in STD_LOGIC;
punt_byte: in STD_LOGIC_VECTOR (1 downto 0);
load_new: out STD_LOGIC;
inc_punt: out STD_LOGIC;
inc_sel_byte: out STD_LOGIC;
reset_sel_byte: out STD_LOGIC;
ENespera64: out STD_LOGIC;
ENespera128: out STD_LOGIC;
ready: out STD_LOGIC;
preset_div: out STD_LOGIC;
reset_div: out STD_LOGIC;
OESCL: out STD_LOGIC;
reset_bit: out STD_LOGIC;
load_bit: out STD_LOGIC;
OESDA: out STD_LOGIC
);
end component;
-- Biestable que contiene el bit que se esta Tx.
-- Este componente sirve para mantener el bit a transmitir.
component tx_bit port (
reset: in STD_LOGIC;
reloj: in STD_LOGIC;
clear: in STD_LOGIC;
D: in STD_LOGIC;
LE: in STD_LOGIC;
Q: out STD_LOGIC
);
end component;
-- Pad de entrada/salida para SDA.
-- Controla el estado de alta impedancia (pull-up) de salida
-- de la linea SDA permitiendo asi la recepcion del ACK por
-- parte del procesado
component IOpad port (
OE: in STD_LOGIC;
SAL: in STD_LOGIC;
ENT: out STD_LOGIC;
PAD: inout STD_LOGIC
);
end component;
-- Contador de espera. Espera 64 Tclk tras
-- bajar el reset para generar una senal de
-- fin de cuenta.
component cont_espera64 port (
reset: in STD_LOGIC;
reloj: in STD_LOGIC;
enable: in STD_LOGIC;
fin: out STD_LOGIC
);
end component;
-- Contador de espera. Espera 128 Tclk tras
-- bajar el reset para generar una senal de
-- fin de cuenta.
component cont_espera128 port (
reset: in STD_LOGIC;
reloj: in STD_LOGIC;
enable: in STD_LOGIC;
fin: out STD_LOGIC
);
end component;
-- Definimos otra FSM encargada de generar los datos a enviar
-- mediante I2C al procesador de video. Su funcion sera la de
-- generar dichos datos y proporcionar la senal de inicio de
-- transferencia, asi como, evaluar el resultado de la misma.
component FSM_gen_datos
port (
reloj: in STD_LOGIC;
reset: in STD_LOGIC;
inicio: in STD_LOGIC;
ready: in STD_LOGIC;
punt_byte: in STD_LOGIC_VECTOR (1 downto 0);
fin_espera128: in STD_LOGIC;
punt_mem: in STD_LOGIC_VECTOR (6 downto 0);
trans: out STD_LOGIC;
dir: out STD_LOGIC_VECTOR (7 downto 0);
dato: out STD_LOGIC_VECTOR (7 downto 0);
ENespera128: out STD_LOGIC;
reset_punt_mem: out STD_LOGIC;
inc_punt_mem: out STD_LOGIC;
resultado: out STD_LOGIC_VECTOR (3 downto 0);
conf_valida: out STD_LOGIC
);
end component;
-- Definimos otro contador-puntero de 7 bits para direccionar la memoria basada
-- en registros que contiene los datos de configuracion del procesador de video.
component contador_REG port (
reset: in STD_LOGIC;
reloj: in STD_LOGIC;
clear: in STD_LOGIC;
inc: in STD_LOGIC;
cont: out STD_LOGIC_VECTOR (6 downto 0)
);
end component;
-- Maquina de estados que controla la recepcion de los asentimientos acki
-- procedentes de los decodificadores de video. Se encarga de generar una
-- unica senal ACK que indicara a la maquina fsm_i2c que la transferencia
-- ha sido correcta.
component FSM_ACK port (
reloj: in STD_LOGIC;
reset: in STD_LOGIC;
ack1: in STD_LOGIC;
ack2: in STD_LOGIC;
ack3: in STD_LOGIC;
ACK: out STD_LOGIC
);
end component;
end libreria_i2c;
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
entity divisor is
port (
reset: in STD_LOGIC;
reloj: in STD_LOGIC;
clear: in STD_LOGIC;
set: in STD_LOGIC;
SCL: out STD_LOGIC
);
end divisor;
architecture divisor_arch of divisor is
signal cuenta: std_logic_vector(7 downto 0);
begin
process (reset,reloj,clear,set)
begin
if (reset = '1') then
cuenta <= (others => '0');
else
if (reloj'event and reloj = '1') then
if(clear='1') then
cuenta<=(others=>'0');
elsif(set='1') then
cuenta<= "10000000";
else
cuenta <= cuenta + '1';
end if;
end if;
end if;
end process;
SCL<=cuenta(7);
end divisor_arch;
library IEEE;
use IEEE.std_logic_1164.all;
entity bufferZ is
port (ent : in STD_LOGIC;
OE : in STD_LOGIC;
sal : out STD_LOGIC
);
end bufferZ;
architecture bufferZ_arch of bufferZ is
begin
process (ent,OE)
begin
if (OE='1') then
sal <= ent;
else
sal <= 'Z';
end if;
end process;
end bufferZ_arch;
library IEEE;
use IEEE.std_logic_1164.all;
entity registro is
port (
reset: in STD_LOGIC;
reloj: in STD_LOGIC;
LE: in STD_LOGIC;
dat_in: in STD_LOGIC_VECTOR (7 downto 0);
dat_out: out STD_LOGIC_VECTOR (7 downto 0)
);
end registro;
architecture registro_arch of registro is
begin
process(reset,reloj,LE)
begin
if (reset = '1') then
dat_out <= (others => '0');
else
if (reloj'event and reloj = '1') then
if (LE = '1') then
dat_out<=dat_in;
end if;
end if;
end if;
end process;
end registro_arch;
library IEEE;
use IEEE.std_logic_1164.all;
entity mux_byte is
port (
byte2: in STD_LOGIC_VECTOR (7 downto 0);
byte1: in STD_LOGIC_VECTOR (7 downto 0);
byte0: in STD_LOGIC_VECTOR (7 downto 0);
sel: in STD_LOGIC_VECTOR (1 downto 0);
byte_sal: out STD_LOGIC_VECTOR (7 downto 0)
);
end mux_byte;
architecture mux_byte_arch of mux_byte is
begin
with sel select
byte_sal <= byte2 when "10",
byte1 when "01",
byte0 when others;
end mux_byte_arch;
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
entity contador_byte is
port (
reset: in STD_LOGIC;
reloj: in STD_LOGIC;
clear: in STD_LOGIC;
inc: in STD_LOGIC;
cont: out STD_LOGIC_VECTOR (1 downto 0)
);
end contador_byte;
architecture contador_byte_arch of contador_byte is
signal cuenta: std_logic_vector (1 downto 0);
begin
process(reset,reloj,clear,inc)
begin
if (reset = '1') then
cuenta <= (others => '0');
elsif (reloj'event and reloj = '1') then
if (clear = '1') then
cuenta <= (others => '0');
elsif (inc = '1') then
cuenta <= cuenta + '1';
end if;
end if;
end process;
cont <= cuenta;
end contador_byte_arch;
library IEEE;
use IEEE.std_logic_1164.all;
entity mux is
port (
ent: in STD_LOGIC_VECTOR (7 downto 0);
sel: in STD_LOGIC_VECTOR (2 downto 0);
sal: out STD_LOGIC
);
end mux;
architecture mux_arch of mux is
begin
with sel select
sal <= ent(7) when "000",
ent(6) when "001",
ent(5) when "010",
ent(4) when "011",
ent(3) when "100",
ent(2) when "101",
ent(1) when "110",
ent(0) when others;
end mux_arch;
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
entity contador is
port (
reset: in STD_LOGIC;
reloj: in STD_LOGIC;
inc: in STD_LOGIC;
cont: out STD_LOGIC_VECTOR (2 downto 0)
);
end contador;
architecture contador_arch of contador is
signal cuenta: std_logic_vector (2 downto 0);
begin
process(reset,reloj,inc)
begin
if (reset = '1') then
cuenta <= (others => '0');
elsif (reloj'event and reloj = '1') then
if (inc = '1') then
cuenta <= cuenta + '1';
end if;
end if;
end process;
cont <= cuenta;
end contador_arch;
library IEEE;
use IEEE.std_logic_1164.all;
entity FSM_I2C is
port(
reloj: in STD_LOGIC;
reset: in STD_LOGIC;
trans: in STD_LOGIC;
fin_espera64: in STD_LOGIC;
fin_espera128: in STD_LOGIC;
puntero: in STD_LOGIC_VECTOR (2 downto 0);
SDAent: in STD_LOGIC;
SCL: in STD_LOGIC;
punt_byte: in STD_LOGIC_VECTOR (1 downto 0);
load_new: out STD_LOGIC;
inc_punt: out STD_LOGIC;
inc_sel_byte: out STD_LOGIC;
reset_sel_byte: out STD_LOGIC;
ENespera64: out STD_LOGIC;
ENespera128: out STD_LOGIC;
ready: out STD_LOGIC;
preset_div: out STD_LOGIC;
reset_div: out STD_LOGIC;
OESCL: out STD_LOGIC;
reset_bit: out STD_LOGIC;
load_bit: out STD_LOGIC;
OESDA: out STD_LOGIC
);
end FSM_I2C;
architecture FSM_I2C_arch of FSM_I2C is
type TipoEstado is (reposo,captura_datos,cond_start,esp_SCL0,
espera_64,envia_bit,esp_SCL1,hold_bit,
nuevo_bit,mira_puntero,incrementa_puntero,
espera_cargar_bit,reset_puntero,
comprueba_ACK1,comprueba_ACK2,comprueba_ACK3,
sig_byte,esp_SCL0_sigbyte,esp_sig_dato,
carga_nuevo_bit,set_punt_byte,STOP1,STOP2,
STOP3,STOP4,STOP5,STOP6
);
signal actual,siguiente: TipoEstado;
begin
transiciones:process(actual,trans,SCL,fin_espera64,puntero,
SDAent,punt_byte,fin_espera128)
begin
case actual is
when reposo =>
-- En este estado, tanto SCL como SDA
-- estan en alta impedancia (pull-up).
-- Hemos de preparar el divisor que
-- usamos para generar SCL, para que
-- comience desde '1' y no desde '0'.
-- La generacion de SCL no comienza
-- mientras preset_div o reset_div
-- esten a '1'.
-- En cuanto a SDA, mantenemos la linea
-- en alta impedancia, pero cargamos
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -