每次计数器更新(可变整数范围)怎么可能发送一点?
How is it possible to send out a bit every counter update (variable integer range)?
我已经用 VHDL(简单)为我的 I2S 收发器编写了代码。我必须知道如何在每次计数器更新 1、2、3 之后发送(24 位)I2S 字的 24 位之一(带有简短语句)。例如:
if cnt = 2 => load bit 1 of left channel
if cnt = 3 => load bit 2
if cnt = 25 => load bit 24 of left channel
if cnt = 26 => load bit 1 of right channel
if cnt = 48 => load bit 24 of right channel
如您所见,我代码中的 WS 选择了左声道或右声道。在我的测试平台中,我添加了测试字(2 x 24 位字)。
它是并行数据输入和串行输出 (PISO),因此它必须类似于移位寄存器。
最近一直在研究VHDL,因为我是VHDL的新手,但是我不知道该怎么做。
在这里你可以看到我写的代码。也许这是一个愚蠢的问题,但我已经搜索了整个互联网。预先感谢您回答我的问题。
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity Simple_I2S_transceiver_V1 is
generic (
DATAWIDTH: integer := 24
);
port
(
RST : in std_logic;
SCK : in std_logic; -- Serial Clock
BCLK : in std_logic; -- Bit Clock
WS : inout std_logic; -- Word Select or Left/Right channel select
SD : out std_logic; -- Serial Data
PDL : in std_logic_vector(DATAWIDTH - 1 downto 0); -- Parallel Data Left
PDR : in std_logic_vector(DATAWIDTH - 1 downto 0); -- Parallel Data Right
UPD : inout std_logic; -- Update data
READY : out std_logic; -- check if data is ready to send (it depends on "VALID")
VALID : out std_logic -- Check if data is valid (length)
);
end Simple_I2S_transceiver_V1;
architecture behavior of Simple_I2S_transceiver_V1 is
signal PDL_BUF : std_logic_vector(DATAWIDTH - 1 downto 0);
signal PDR_BUF : std_logic_vector(DATAWIDTH - 1 downto 0);
begin
process(BCLK)
-- Declaration of optional variables
variable bitcounter : integer range 0 to 48;
begin
-------------------------------------------------
-- RESET all
-------------------------------------------------
if RST = '1' then
WS <= '0';
SD <= '0';
READY <= '0';
VALID <= '0';
UPD <= '0';
PDL_BUF <= (OTHERS => '0'); -- Clear left channel buffer
PDR_BUF <= (OTHERS => '0'); -- Clear right channel buffer
-------------------------------------------------
-- Set WS / left/right-channel
-------------------------------------------------
elsif (BCLK'event and BCLK = '1') then
PDL_BUF <= PDL;
PDR_BUF <= PDR;
bitcounter := bitcounter + 1;
if bitcounter = 1 then
UPD <= '1';
else
UPD <= '0';
if bitcounter >= 1 and bitcounter <= 24 then
WS <= '0';
else
WS <= '1';
UPD <= '0';
if WS = '0' then
SD <= PDL(23); <-- Parallel load -> it has to be serial load
elsif WS = '1' then
SD <= PDR(23); <-- The same as PDL
if bitcounter = 48 then
bitcounter := 0;
----------------------------------------------
-- transmitt data
----------------------------------------------
-- add transmission
end if;
end if;
end if;
end if;
end if;
end process;
end behavior;
由于I2S是MSB在前,左移并使用PDx的MSbit作为SD输出,类似的。
左声道(发射)
SD <= PDL_BUF (23); -- use most significant bit
PDL_BUF <= PDL_BUF (22 downto 0) & '0'; -- 22nd bit becomes 23 and puts a zero into unused bit 0
右声道类似。对于接收,您仍然需要向左移动。
抱歉,我对 I2S 了解不多,但是
- 加载时要小心 PDL/PDR 以便在发送时不能修改它们(state machine 也许?)
- 同时将数据时钟输出设置为高电平时发送数据时要小心,您可能希望在数据时钟的下降沿输出数据,以便数据在另一侧的上升沿正确锁存正确。您始终可以对时钟进行状态机 - 但这会降低数据速率。
- 知道何时在传输时在 WS 0 和 1 之间切换
我已经用 VHDL(简单)为我的 I2S 收发器编写了代码。我必须知道如何在每次计数器更新 1、2、3 之后发送(24 位)I2S 字的 24 位之一(带有简短语句)。例如:
if cnt = 2 => load bit 1 of left channel
if cnt = 3 => load bit 2
if cnt = 25 => load bit 24 of left channel
if cnt = 26 => load bit 1 of right channel
if cnt = 48 => load bit 24 of right channel
如您所见,我代码中的 WS 选择了左声道或右声道。在我的测试平台中,我添加了测试字(2 x 24 位字)。
它是并行数据输入和串行输出 (PISO),因此它必须类似于移位寄存器。
最近一直在研究VHDL,因为我是VHDL的新手,但是我不知道该怎么做。
在这里你可以看到我写的代码。也许这是一个愚蠢的问题,但我已经搜索了整个互联网。预先感谢您回答我的问题。
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity Simple_I2S_transceiver_V1 is
generic (
DATAWIDTH: integer := 24
);
port
(
RST : in std_logic;
SCK : in std_logic; -- Serial Clock
BCLK : in std_logic; -- Bit Clock
WS : inout std_logic; -- Word Select or Left/Right channel select
SD : out std_logic; -- Serial Data
PDL : in std_logic_vector(DATAWIDTH - 1 downto 0); -- Parallel Data Left
PDR : in std_logic_vector(DATAWIDTH - 1 downto 0); -- Parallel Data Right
UPD : inout std_logic; -- Update data
READY : out std_logic; -- check if data is ready to send (it depends on "VALID")
VALID : out std_logic -- Check if data is valid (length)
);
end Simple_I2S_transceiver_V1;
architecture behavior of Simple_I2S_transceiver_V1 is
signal PDL_BUF : std_logic_vector(DATAWIDTH - 1 downto 0);
signal PDR_BUF : std_logic_vector(DATAWIDTH - 1 downto 0);
begin
process(BCLK)
-- Declaration of optional variables
variable bitcounter : integer range 0 to 48;
begin
-------------------------------------------------
-- RESET all
-------------------------------------------------
if RST = '1' then
WS <= '0';
SD <= '0';
READY <= '0';
VALID <= '0';
UPD <= '0';
PDL_BUF <= (OTHERS => '0'); -- Clear left channel buffer
PDR_BUF <= (OTHERS => '0'); -- Clear right channel buffer
-------------------------------------------------
-- Set WS / left/right-channel
-------------------------------------------------
elsif (BCLK'event and BCLK = '1') then
PDL_BUF <= PDL;
PDR_BUF <= PDR;
bitcounter := bitcounter + 1;
if bitcounter = 1 then
UPD <= '1';
else
UPD <= '0';
if bitcounter >= 1 and bitcounter <= 24 then
WS <= '0';
else
WS <= '1';
UPD <= '0';
if WS = '0' then
SD <= PDL(23); <-- Parallel load -> it has to be serial load
elsif WS = '1' then
SD <= PDR(23); <-- The same as PDL
if bitcounter = 48 then
bitcounter := 0;
----------------------------------------------
-- transmitt data
----------------------------------------------
-- add transmission
end if;
end if;
end if;
end if;
end if;
end process;
end behavior;
由于I2S是MSB在前,左移并使用PDx的MSbit作为SD输出,类似的。
左声道(发射)
SD <= PDL_BUF (23); -- use most significant bit
PDL_BUF <= PDL_BUF (22 downto 0) & '0'; -- 22nd bit becomes 23 and puts a zero into unused bit 0
右声道类似。对于接收,您仍然需要向左移动。
抱歉,我对 I2S 了解不多,但是
- 加载时要小心 PDL/PDR 以便在发送时不能修改它们(state machine 也许?)
- 同时将数据时钟输出设置为高电平时发送数据时要小心,您可能希望在数据时钟的下降沿输出数据,以便数据在另一侧的上升沿正确锁存正确。您始终可以对时钟进行状态机 - 但这会降低数据速率。
- 知道何时在传输时在 WS 0 和 1 之间切换