Bueno lo prometido es deuda.
Aqui os pongo el código para manejar un códec en VHDL. En primer lugar deciros que no lo he probao, es decir, lo tenía escrito en VERILOG y lo he pasado a VHDL, osea que puede haber errores de sintáxis algún ";" que se haya olvidao etc. Revisarlo.
El diseño es un módulo para manejar el ADC, otro para el DAC y otro que los une y genera los relojes. Los módulos están diseñados para una frecuencia de reloj de 50MHz.
Módulo ADC:
Codigo:
--------------------------------------------------------------------------------
-- Modulo para leer de un codec en formato I2S.
-- Los datos vienen en serie por el pin "data_in".
-- Los datos de audio se entregan por los buses "data_out_l" y "data_out_r"
-- correspondoientes a las salidas izquierda y derecha de la señal de audio.
-- La señal "count clk" proviene del módulo "top" y sirve para sincronizar
-- los frames de audio.
--------------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use ieee.numeric_std.all;
entity adc is
port (
clk : in std_logic;
rst : in std_logic;
data_out_l : out std_logic_vector(31 downto 0);
data_out_r : out std_logic_vector(31 downto 0);
data_in : in std_logic;
count_clk : in std_logic_vector(5 downto 0)
);
end entity adc;
architecture behavioral of adc is
signal shift_reg : std_logic_vector(32 downto 0);
begin -- architecture behavioral
SHIFT_REG_PROC : process(clk, rst) is
begin
if (rst="1") then
shift_reg <= 0;
data_out_l <= 0;
data_out_r <= 0;
elsif (clk"event and clk="1") then
if (count_clk="111110"
then
data_outl <= shift_reg(60 downto 37) & X"00";
data_outl <= shift_reg(28 downto 5) & X"00";
else
shift_reg <= shift_reg(62 downto 0) & data_in;
end if;
end if;
end process SHIFT_REG_PROC;
end architecture behavioral;
Módulo DAC
Codigo:
--------------------------------------------------------------------------------
-- Modulo para escribir en un codec en formato I2S.
-- Los datos vienen en paralelo por los buses "data_in_l" y "data_in_r".
-- Los datos de audio se entregan en serie po la señal "data_out".
-- La señal "count clk" proviene del módulo "top" y sirve para sincronizar
-- los frames de audio.
--------------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use ieee.numeric_std.all;
entity dac is
port (
clk : in std_logic;
rst : in std_logic;
data_in_l : in std_logic_vector(31 downto 0);
data_in_r : in std_logic_vector(31 downto 0);
data_out : out std_logic;
count_clk : in std_logic_vector(5 downto 0)
);
end entity dac;
architecture behavioral of dac is
signal shift_reg : std_logic_vector(32 downto 0);
begin -- architecture behavioral
SHIFT_REG_PROC : process(clk, rst) is
begin
if (rst="1") then
shift_reg <= 0;
elsif (clk"event and clk="1") then
if (count_clk="111111"
then
shift_reg <= data_in_l & data_in_r;
else
shift_reg <= shift_reg(62 downto 0) & "0";
end if;
end if;
end process SHIFT_REG_PROC;
data_out <= shift_reg(63);
end architecture behavioral;
Y el top
Codigo:
--------------------------------------------------------------------------------
-- Modulo que genera los relojes y se comunica con los módulos del adc y del dac.
-- La frecuencia para el reloj "clk" es de 50MHz obligatoriamente
-- La frecuencia de muestreo del sistema es de 48.8KHz
--------------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use ieee.numeric_std.all;
entity top_codec is
port (
clk : in std_logic;
rst : in std_logic;
data_in : in std_logic_vector(31 downto 0);
sck : out std_logic;
bck : out std_logic;
lrck : out std_logic;
data_out : out std_logic;
count_clk : in std_logic_vector(5 downto 0)
);
end entity top_codec;
architecture behavioral of top_codec is
signal count_clk : std_logic_vector(9 downto 0);
signal datal_in : std_logic_vector(31 downto 0);
signal datar_in : std_logic_vector(31 downto 0);
signal datal_out : std_logic_vector(31 downto 0);
signal datar_out : std_logic_vector(31 downto 0);
-- Conversor analógico a digital
component adc is
port (
clk : in std_logic;
rst : in std_logic;
data_out_l : out std_logic_vector(31 downto 0);
data_out_r : out std_logic_vector(31 downto 0);
data_in : in std_logic;
count_clk : in std_logic_vector(5 downto 0)
);
end component adc;
-- Conversor digital a analógico
component dac is
port (
clk : in std_logic;
rst : in std_logic;
data_in_l : in std_logic_vector(31 downto 0);
data_in_r : in std_logic_vector(31 downto 0);
data_out : out std_logic;
count_clk : in std_logic_vector(5 downto 0)
);
end component dac;
begin -- architecture behavioral
COUNT_CLK_PROC : process(clk, rst) is
begin
if (rst="1") then
count_clk <= 0;
else
count_clk <= count_clk + 1;
end if;
end process COUNT_CLK_PROC;
LRCK_PROC : process(clk, rst) is
begin
if (rst="1") then
lrck <= 0;
else
lrck <= count_clk(9); -- (fs) 48.8 KHz
end if;
end process LRCK_PROC;
bck <= count_clk(3); -- 3.125 MHz (64fs)
sck <= count_clk(1); -- 12.5 MHz (256fs)
-- 64fs = 50 MHz/16 -> fs = 48.828KHz
-- La frecuencia de muestreo se fija en 48 KHz para un reloj de entrada de 50MHz
datal_in <= datal_out;
datar_in <= datar_out;
-- ADC
adc_i : adc
port map (
clk => bck, -- in std_logic;
rst => rst, -- in std_logic;
data_out_l => datal_out, -- out std_logic_vector(31 downto 0);
data_out_r => datar_out, -- out std_logic_vector(31 downto 0);
data_in => data_in, -- in std_logic;
count_clk => count_clk(9 downto 4)); -- in std_logic_vector(5 downto 0)
-- DAC
dac_i : dac
port map (
clk => bck, -- in std_logic;
rst => rst, -- in std_logic;
data_in_l => datal_in, -- in std_logic_vector(31 downto 0);
data_in_r => datar_in, -- in std_logic_vector(31 downto 0);
data_out => data_out, -- out std_logic;
count_clk => count_clk(9 downto 4)); -- in std_logic_vector(5 downto 0)
end architecture behavioral;