Как можно отправлять бит при каждом обновлении счетчика (диапазон переменных целых чисел)?

#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, но

  1. будьте осторожны при загрузке PDL / PDR, чтобы их нельзя было изменить во время отправки (возможно, конечный автомат?)
  2. будьте осторожны при отправке данных при одновременной настройке синхронизации данных на высоком уровне, возможно, вам захочется выводить данные на падающем фронте синхронизации данных, чтобы данные правильно фиксировались на восходящем фронте с другой стороны. правильно. Вы всегда можете указать тактовую частоту — однако это приведет к снижению скорости передачи данных.
  3. знайте, когда переключаться между WS 0 и 1 при передаче

Комментарии:

1. «Отправлять данные по одному краю, чтобы их было легче получать по другому краю» — распространенная ошибка, допускаемая многими разработчиками. Это неаккуратно. Также это НЕ соответствует стандарту I2S.

2. Как уже было сказано, я не очень осведомлен о i2s. Я хотел бы узнать, как лучше избегать неаккуратных действий, если вы можете уточнить. Хотя трудно не задать вопрос самостоятельно!

3. Мой интерфейс I2S является только передатчиком. Итак, в этом случае мне не нужно получать данные. Но спасибо, что помогли мне до сих пор.

4. 1 / Вы теряете половину тактового периода, что вдвое снижает максимальную скорость передачи данных. Таким образом, ваше время нарастания / спада также должно быть быстрее. 2 / Вам нужны хорошие симметричные часы, иначе вы потеряете больше времени. 3 / Вы используете половину времени ожидания, что очень мало по сравнению со временем настройки или даже отрицательно.

5. это верно. Но я все еще не получил ответа. Я должен знать, как можно передавать один бит из 24 бит при каждом обновлении счетчика. Или, другими словами, как перейти от параллельного ввода к последовательному выводу данных (возможно, с помощью сдвигового регистра). Я надеюсь, что это возможно с помощью короткого оператора (if-else).