#integer #range #vhdl #counter
#целое число #диапазон #vhdl #счетчик
Вопрос:
Я создал код для своего приемопередатчика I2S на VHDL (простой). Я должен знать, как можно отправлять после каждого обновления счетчика 1,2,3 один из 24 битов (24-битного) слова I2S (с коротким оператором). например:
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 х 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;
Ответ №1:
Поскольку I2S является первым MSB, сдвиньте влево и используйте MSbit PDx для вывода SD, что-то вроде.
Для левого канала (передача)
SD <= PDL_BUF (23); -- use most significant bit
PDL_BUF <= PDL_BUF (22 downto 0) amp; '0'; -- 22nd bit becomes 23 and puts a zero into unused bit 0
Аналогично для правого канала. Для получения вы все равно захотите сдвинуть влево.
Извините, я мало что знаю о I2S, но
- будьте осторожны при загрузке PDL / PDR, чтобы их нельзя было изменить во время отправки (возможно, конечный автомат?)
- будьте осторожны при отправке данных при одновременной настройке синхронизации данных на высоком уровне, возможно, вам захочется выводить данные на падающем фронте синхронизации данных, чтобы данные правильно фиксировались на восходящем фронте с другой стороны. правильно. Вы всегда можете указать тактовую частоту — однако это приведет к снижению скорости передачи данных.
- знайте, когда переключаться между WS 0 и 1 при передаче
Комментарии:
1. «Отправлять данные по одному краю, чтобы их было легче получать по другому краю» — распространенная ошибка, допускаемая многими разработчиками. Это неаккуратно. Также это НЕ соответствует стандарту I2S.
2. Как уже было сказано, я не очень осведомлен о i2s. Я хотел бы узнать, как лучше избегать неаккуратных действий, если вы можете уточнить. Хотя трудно не задать вопрос самостоятельно!
3. Мой интерфейс I2S является только передатчиком. Итак, в этом случае мне не нужно получать данные. Но спасибо, что помогли мне до сих пор.
4. 1 / Вы теряете половину тактового периода, что вдвое снижает максимальную скорость передачи данных. Таким образом, ваше время нарастания / спада также должно быть быстрее. 2 / Вам нужны хорошие симметричные часы, иначе вы потеряете больше времени. 3 / Вы используете половину времени ожидания, что очень мало по сравнению со временем настройки или даже отрицательно.
5. это верно. Но я все еще не получил ответа. Я должен знать, как можно передавать один бит из 24 бит при каждом обновлении счетчика. Или, другими словами, как перейти от параллельного ввода к последовательному выводу данных (возможно, с помощью сдвигового регистра). Я надеюсь, что это возможно с помощью короткого оператора (if-else).